繁体   English   中英

在具有外部链接的匿名命名空间中声明的实体示例

[英]Example of entity declared in a anonymous namespace that has external linkage

鉴于§3.5/ 4中的以下语句(强调我的)和§7.3.1.1/ 1中的注释[94],我想在一个具有外部链接的未命名命名空间中声明的实体的一个单独示例。

§3.5/ 4

未命名的命名空间或在未命名的命名空间中直接或间接声明的命名空间具有内部链接 所有其他名称空间都有外部链接。 具有名称空间作用域的名称上面没有给出内部链接,如果是名称,则具有与封闭名称空间相同的链接

  • 一个变量; 要么
  • 功能; 要么
  • 命名类(第9节),或在typedef声明中定义的未命名类,其中类具有用于链接目的的typedef名称(7.1.3); 要么
  • 命名枚举(7.2),或在typedef声明中定义的未命名枚举,其中枚举具有用于链接目的的typedef名称(7.1.3); 要么
  • 属于具有链接的枚举的枚举器; 要么
  • 一个模板。

关于§7.3.1.1/ 1的注释[94]:

虽然未命名的命名空间中的实体可能具有外部链接,但它们实际上由其翻译单元唯一的名称限定,因此永远不会从任何其他翻译单元中看到。

您正在查看标准中的缺陷。

使得未命名的命名空间成员具有内部链接的更改在2010年11月的C ++ 11标准化过程中发生得相当晚( CWG issue 1113 )。 因此,标准中的许多地方需要改变,但事实并非如此。 其中一个是你引用的脚注。

CWG问题1603 ,目前处于“就绪”状态(阅读:该决议可能会在下次委员会会议上通过),将解决此问题以及与向未命名的命名空间成员提供内部链接相关的许多其他问题。

这是一个很好的问题,因为它很难证明。 我们可以利用C ++标准中的其他规则来显示匿名命名空间中的变量可以具有外部链接。

使用外部链接对int *进行模板化将成功,而对内部链接的int *进行模板化将失败。

#include <iostream>

namespace {
    // not externally linked, won't compile
    // const int i = 5;

    // external linkage, compiles
    extern int i;
    int i = 5;
}

template<int* int_ptr>
struct temp_on_extern_linked_int {
    temp_on_extern_linked_int() {
        std::cout << *int_ptr << std::endl;
    }
};

int main() {
    temp_on_extern_linked_int<&i>();
}

如图所示,程序编译并运行。

$ g++-4.8 main.cpp -o main
$ ./main
5

取消注释i的其他定义会导致编译失败。

$ g++-4.8 main.cpp -o main
main.cpp: In function 'int main()':
main.cpp:17:30: error: '& {anonymous}::i' is not a valid template argument of
type 'int*' because '{anonymous}::i' does not have external linkage
  temp_on_extern_linked_int<&i>();
                              ^

编译器非常有用。 它明确指出,因为i没有外部链接,编译失败了。

i的注释定义具有内部链接,因为它是没有extern的限定const。 (§3.4.6)

Variables at namespace scope that are declared const and not extern have internal linkage.

部分技巧不是编译为C ++ 11。

为什么C ++ 03需要模板参数来进行外部链接?

例如

#include <iostream>

namespace
{
    extern int x = 10;

    void f( int y )
    {
        extern int x;
        std::cout << x + y << std::endl;
    }
}

int main() 
{
    int y =  15;

    f( y );

    return 0;
}

根据C ++标准

6块作用域中声明的函数的名称和块作用域外部声明声明的变量的名称具有链接。 如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接。 如果存在多个这样的匹配实体,则该程序是不正确的。 否则,如果未找到匹配的实体,则块范围实体接收外部链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM