根据标准委员会的说法,为什么匿名名称空间不能充分替代静态名称空间?

Why are anonymous namespaces not a sufficient replacement for namespace-static, according to the standards committee?

本文关键字:空间 不能 静态 委员会 标准 为什么      更新时间:2023-10-16

根据这个答案,命名空间作用域的静态变量在c++ 11中没有被弃用。也就是说,它们在c++ 03中被弃用了,因为匿名命名空间被认为更好。但是c++ 11不推荐它们。

为什么?N3296将此原因列出如下:

不应该反对在命名空间范围内使用static。匿名命名空间不足以替代该功能。

这显然被委员会接受了。为什么?为什么匿名名称空间不能完全取代这个功能呢?

我更希望答案有一些标准委员会讨论的文档或书面记录。

这是一个更深入的解释。

虽然7.3.1.1[命名空间。声明不赞成使用static关键字在命名空间范围内声明变量,因为未命名的命名空间提供了一个更好的选择,在可预见的将来,这个特性不太可能被删除,特别是考虑到C的兼容性问题。委员会应考虑取消弃用。

我知道的一个问题是,匿名命名空间不能专门化命名空间块之外的模板。这就是引入inline namespace的原因,尽管static也可以工作。此外,static可以很好地处理宏。

对于未命名的名称空间,您不能在当前所在的名称空间内提供变量内部链接。对于static,你可以。例如,以下未命名名称空间的使用不会提供全局变量的内部链接

namespace { int a; } 
int a; // oops, no error!

如果第一个a被声明为static,那么尝试在全局作用域中声明第二个a将立即出错,因为第一个a已经在全局作用域中存在。

因此,为了实现使标识唯一的工作,未命名的名称空间将实体放置到不同的名称空间中(除了影响它们的链接之外)。static 只有影响链接,函数和变量所属的命名空间保持不变。

一线用户的回答是,未命名的名称空间(匿名名称空间的标准术语)中的名称具有外部链接,而在名称空间级别声明static的名称具有内部链接。

内部链接有两个优点,其中只有一个是未命名的名称空间提供的:

  1. 它们使翻译单元的名称本地化。我可以在不同的翻译单元中对同一个函数fun进行不同的定义,而不违反单一定义规则。此属性由未命名命名空间中的名称共享,方法是使用唯一的命名空间名称来修饰它们。

  2. 它们阻止名称进入全局符号表。这是一个严格的优化,但在实践中很重要。

因此,一般来说,使用static作为其翻译单元局部命名空间级函数的程序为链接器生成的工作更少,并且可能比使用未命名命名空间的等效程序执行得更快。

也就是说,对于想要作为模板参数传递的类型,您需要使用未命名的名称空间,因为模板参数必须具有外部链接。

所以我通常这样做:将自由函数定义为static,但将类型放入未命名的命名空间。