在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 '::')
:/
答案 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语句指定命名空间,或者在未命名的命名空间内完全限定对其他命名空间的引用...