2014-09-24 21 views
7

鉴于以下声明(重点介绍)在§3.5/ 4和§7.3.1.1/ 1的注释[94]中,我希望有一个在具有外部链接的未命名名称空间中声明的实体的单个示例。在具有外部链接的匿名名称空间中声明的实体的示例

§3.5/ 4

具名命名空间或具名命名空间内直接或间接地声明 一个命名空间具有内部连接。所有其他名称空间 都有外部链接。 尚未以上 给定的内部键的具有名称命名空间范围具有相同的连锁作为包封 命名空间,如果它是

  • 变量的名字;或
  • 一个函数;或
  • 一个命名的类(第9章),或在typedef声明中定义的未命名类,其中该类具有用于链接 目的(7.1.3)的typedef名称;或
  • 一个已命名的枚举(7.2),或一个在typedef声明中定义的未命名枚举,其中枚举具有用于 链接目的(7.1.3)的typedef名称;或
  • 枚举器属于枚举与连接;或
  • 模板。

注[94]在§7.3.1.1/ 1:

虽然具名命名空间的实体可能有外部链接, 他们有效地独有的翻译 名合格单位,因此永远不能从任何其他翻译单位看到。

+2

我怀疑脚注可能是C++ 03中的一个剩余部分,其中未命名名称空间中的名称具有外部链接(因为否则它们不能用作模板参数)。作者只是忘记删除它。 – 2014-09-25 01:00:46

回答

5

您正在寻找在标准的缺陷。

在2010年11月的C++ 11标准化过程(CWG issue 1113)中,使得未命名名称空间成员具有内部链接的更改发生得相当晚。结果,标准中的一些地方需要改变,但不是。其中之一就是你引用的脚注。

CWG issue 1603目前处于“准备好”状态(阅读:该决议很可能在下一次委员会会议上通过),将解决此问题以及其他一些与给未命名名称空间成员进行内部链接有关的其他问题。

+0

这就是我正在寻找的。很好的回答(+1)。 – 2014-09-25 14:08:18

0

例如

#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的名称和一个 可变的由块范围extern声明声明的名称有联系。如果 有一个实体的可见声明,并且具有相同名称和类型的链接,则忽略在最内层的 之外声明的实体,这些实体包含名称空间作用域,则该作用域声明声明该实体并接收前一个声明的链接。如果 有多个这样的匹配实体,则该程序是 不合格。否则,如果找不到匹配的实体,则该作用域实体接收外部链接

+0

我相信§3.5/ 2第一个要点中的'or'不是唯一的。所以,我不同意'x'在你的例子中有外部链接。 – 2014-09-24 21:46:41

+0

@启动巴西x Os自动使用quakifier extern声明的变量。因此,如果在带有链接的封闭名称空间中有前面的x声明,那么x具有相同的链接。参见3.5/6。 – 2014-09-25 03:40:49

+0

§3.5/ 6只是告诉你,本地'x'与命名空间范围'extern int x = 10;'中声明的'x'具有相同的链接。但这并不意味着这个'x'具有外部联系。请参阅§3.5/ 4第一个要点:'名称空间范围内没有 上面给定的内部链接的名称与封闭名称空间具有相同的链接,如果它是 - 变量的名称;'。关于与“extern”说明符一起声明的名称的链接,请参阅关于§3.5的§7.1.1/ 6。 – 2014-09-25 13:54:40

1

这是一个很好的问题,因为它很难证明。我们可以利用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的注释定义具有内部链接,因为它是不受外部限制的const。 (§3.4.6)特技的

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

部分未编译为C++ 11。

Why did C++03 require template parameters to have external linkage?

+0

AFAIK你已经证明,在C++ 03中,匿名的命名空间具有外部链接,因此,你甚至不需要声明'extern int i;',因为编译器认识到声明'int i = 5;'为有外部联系。 – 2014-09-25 12:53:29

+0

对于C++ 11,我只能引用你的标准,但由于你已经在OP中提供了相关的引用,所以你不清楚你在找什么。它有助于了解名称空间和内部的变量不一定具有相同的链接吗? – Praxeolitic 2014-09-25 12:59:39

+0

另外,在C++ 11中改变的例子是模板参数,而不是链接规则。 – Praxeolitic 2014-09-25 13:20:39

相关问题