Неопределенность Анонимного Пространства Имен
Рассмотрим следующий фрагмент:
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 () в вашем пространстве имен, а a ::Foo() вызовет пространство имен в глобальной области.