Анонимная Неопределенность Пространства Имен

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

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's defined in the anonymous namespace (Foo #2).
}

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

5 ответов

Решение

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

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

  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        
}

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

#include <iostream>

using namespace std;

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

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

Единственное решение, которое я могу придумать, это не изменяет существующее расположение пространства имен, это делегировать 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();
}

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

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

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

Другие вопросы по тегам