7

在 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

4 回答 4

10

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

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

A namespace, anonymous or otherwise, has no effect on the linkage of its members. In particular members of an anonymous namespace do not magically get internal linkage.

于 2009-07-10T21:27:47.623 回答
7

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

template class bar<int>;

说是“请在此处实例化类型 int 的类模板栏”。你不能在另一个命名空间中这样做,就像你不能在另一个命名空间中部分特化一个类模板一样。特别是,要显式实例化的模板必须已经定义,并且在您的示例中,没有(匿名命名空间)::bar<>,只有 foo::bar<>。

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

于 2009-07-10T21:26:56.287 回答
6

我想你有你的答案 - 匿名命名空间是不同的、独特的命名空间。顺便说一句,编译器会生成一些随机的大整数来在内部表示该命名空间。

于 2009-07-10T21:18:39.890 回答
0

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

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

于 2009-07-10T21:22:04.097 回答