Анонимное пространство имен Неоднозначность

Рассмотрим следующий фрагмент:

void Foo() // 1
{
}

namespace
{
  void Foo() // 2
  {
  }
}

int main()
{
  Foo(); // Ambiguous.
  ::Foo(); // Calls the Foo in the global namespace (Foo #1).

  // I'm trying to call the `Foo` that defined in the anonymous namespace (Foo #2).
}

Как я могу ссылаться на что-то внутри анонимного пространства имен в этом случае?

Ответы

Ответ 1

Вы не можете. Стандарт содержит следующий раздел (§7.3.1.1, С++ 03):

Определение без имени-namespace ведет себя так, как если бы оно было заменено на

  namespace unique { /* empty body */ }
  using namespace unique;
  namespace unique { namespace-body }

где все вхождения единственного в единицы перевода заменяются тот же идентификатор и этот идентификатор отличается от всех других идентификаторов во всей программе.

Таким образом, вы не можете ссылаться на это уникальное имя.

Однако вы могли бы использовать вместо этого следующее:

int i;

namespace helper {
    namespace {
        int i;
        int j;
    }
}

using namespace helper;

void f() { 
    j++; // works
    i++; // still ambigous
    ::i++; // access to global namespace
    helper::i++; // access to unnamed namespace        
}

Ответ 2

В то время как Георг дает стандартный ответ, правильный, правильный и респектабельный ответ, я хотел бы предложить свое хакерское одно использование другого пространства имен в анонимном пространстве имен:

#include <iostream>

using namespace std;

namespace
{
namespace inner
{
    int cout = 42;
}
}

int main()
{
    cout << inner::cout << endl;
    return 0;
}

Ответ 3

Единственное решение, о котором я могу думать, не изменяет существующее расположение пространства имен - это делегировать main функции в анонимном пространстве имен. (main сам должен быть глобальной функцией (§3.6.1/1), поэтому он не может быть в анонимном пространстве имен.)

void Foo() // 1
{
}

namespace
{
  void Foo() // 2
  {
  }
}

namespace { // re-open same anonymous namespace

    int do_main()
    {
      Foo(); // Calls local, anonymous namespace (Foo #2).
      ::Foo(); // Calls the Foo in the global namespace (Foo #1).

      return 0; // return not optional
    }

}

int main() {
    return do_main();
}

Ответ 4

Единственный реальный способ - поместить код, который вы хотите получить, в это пространство имен в самом пространстве имен. Нет способа разрешить неназванное пространство имен иначе, поскольку у него нет идентификатора, который вы можете дать ему для решения проблемы двусмысленного разрешения.

Если ваш код находится внутри самого пространства имен {}, локальное имя получает приоритет над глобальным, поэтому Foo() вызовет Foo() в вашем пространстве имен, а a:: Foo() вызовет пространство имен в глобальной области.

Ответ 5

Просто переименуйте локальную функцию пространства имен.