2014-09-24 29 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

相關問題