Анонимная Неопределенность Пространства Имен - PullRequest
18 голосов
/ 09 сентября 2010

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

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 ]

18 голосов
/ 09 сентября 2010

Вы не можете.Стандарт содержит следующий раздел ( §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        
}
5 голосов
/ 09 сентября 2010

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

#include <iostream>

using namespace std;

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

int main()
{
    cout << inner::cout << endl;
    return 0;
}
2 голосов
/ 09 сентября 2010

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

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

0 голосов
/ 09 сентября 2010

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

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

...