匿名命名空间是否包含所有命名空间?

时间:2009-07-10 21:11:36

标签: c++ namespaces global anonymous linkage

在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 个答案:

答案 0 :(得分:10)

匿名命名空间在逻辑上等同于

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

匿名或其他命名空间对其成员的链接没有影响。特别是匿名命名空间的成员不会神奇地获得内部链接。

答案 1 :(得分:7)

首先:您是显式实例化类模板,而不是定义新的类模板。什么

template class bar<int>;

说“请在这里为int类型实例化类模板栏”。您不能在另一个命名空间中执行此操作,就像您无法在另一个命名空间中部分地专门化类模板一样。特别是,必须已经定义了要显式实例化的模板,在您的示例中,没有(匿名命名空间):: bar&lt;&gt;,只有foo :: bar&lt;&gt;。

第二:匿名命名空间是一个真正的命名空间(尽管如此,它在每个翻译单元中都是不同的)。它也没有神奇地改变联系。在namespace {}中声明的所有内容仍然具有默认链接,就像在任何其他命名空间范围内一样。 IIRC,它甚至被添加到允许翻译单元 - 私有但外部链接对象。

答案 2 :(得分:6)

我认为你有答案 - 匿名命名空间是独特的,唯一的命名空间。 BETWEEN,编译器生成一些随机大整数以在内部表示该命名空间。

答案 3 :(得分:0)

根据Stroustrup(第8.2.5.1节),全局命名空间可以访问匿名(未命名)命名空间,但它没有明确说出相反的内容。

我希望您必须使用using语句指定命名空间,或者在未命名的命名空间内完全限定对其他命名空间的引用...