Охватывает ли анонимное пространство имен все пространства имен? - PullRequest
7 голосов
/ 11 июля 2009

В C ++ вы указываете внутреннюю связь, заключая определения классов и функций в анонимное пространство имен. Вы также можете явно создавать экземпляры шаблонов, но чтобы стандарты соответствовали любым явным созданиям шаблонов, они должны находиться в одном и том же пространстве имен. AFAICT это должно скомпилироваться, но GCC не работает на нем:

namespace foo {

template<class T>
class bar {};

}

using namespace foo;

namespace {
template class bar<int>;
}

int main()
{
    return 0;
}

С ошибкой:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo')

Что интересно, поскольку анонимное пространство имен должно просто указывать связь, а не функционировать как пространство имен, а глобальное пространство имен определенно включает в себя foo, поскольку оно охватывает каждое пространство имен. Но даже это не работает!:

template<class T>
class bar {};

using namespace foo;

namespace {
template class bar<int>;
}

int main()
{
    return 0;
}

Что не получается с той же ошибкой, просто вместо этого перечисляя глобальное пространство имен:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::')

/

Ответы [ 4 ]

10 голосов
/ 11 июля 2009

Анонимное пространство имен логически эквивалентно

namespace _TU_specific_unique_generated_name
{
    // ...
}
using namespace _TU_specific_unique_generated_name;

Пространство имен, анонимное или иное, не влияет на связь его членов. В частности, члены анонимного пространства имен магически не получают внутреннюю связь.

7 голосов
/ 11 июля 2009

Первое: вы явно создаете экземпляр шаблона класса, а не определяете новый шаблон класса. Что

template class bar<int>;

говорит "пожалуйста, создайте экземпляр панели шаблонов классов для типа int здесь". Вы не можете сделать это в другом пространстве имен, так же как вы не можете частично специализировать шаблон класса в другом пространстве имен. В частности, должен быть определен шаблон, который должен быть явно создан, и в вашем примере нет (анонимного пространства имен) :: bar <>, только foo :: bar <>.

Второе: анонимное пространство имен - это реальное пространство имен (хотя оно отличается в каждой единице перевода). Это также волшебным образом не меняет связь. Все, что объявлено внутри пространства имен {}, по-прежнему имеет связь по умолчанию, как и в любой другой области пространства имен. IIRC, он даже был добавлен, чтобы разрешить перевод частных объектов, но объектов внешней связи.

6 голосов
/ 11 июля 2009

Я думаю, что у вас есть ответ - анонимные пространства имен - это отдельные, уникальные пространства имен. Кстати, компилятор генерирует случайное большое целое число для внутреннего представления этого пространства имен.

0 голосов
/ 11 июля 2009

Согласно Страуструпу (раздел 8.2.5.1), глобальное пространство имен имеет доступ к анонимному (неназванному) пространству имен, но явно не говорит об обратном.

Полагаю, вам придется указывать пространство имен с помощью оператора using или полностью квалифицировать ссылки на другие пространства имен внутри безымянного пространства имен ...

...