2015-06-23 51 views
10

我問自己,爲什麼下面的代碼工作,什麼符extern實例並不時baz_instance使用extern const將結構傳遞給模板。什麼是外部?

struct baz { 
    int value; 
}; 

extern const baz baz_instance = {3}; 

template<baz const& b> 
int foo(){ 
    return b.value; 
} 

int main(){ 
    foo<baz_instance>(); 
    return 1; 
} 

爲什麼擺在首位上面的代碼編譯,爲什麼不把它編譯了,如果extern符被遺漏了嗎? extern說明符在這個例子中做了什麼?

回答

6

這是從C++ 03更改爲C++ 11的標準部分之一。

在C++ 03,[temp.arg.nontype]讀取:

模板參數的用於非類型的,非模板的模板參數應是以下之一:

  • [...]
  • [...]]
  • 的對象或功能與外部聯動,包括功能模板和功能模板的IDS,但不包括非靜態類成員的地址,表示爲& ID-表達其中&是可選的,如果名稱是指一個函數或數組,或者如果相應的模板參數是引用;或
  • [...]

在C++ 11中,得到了更新的issue 1155結果,儘管GCC仍然有a bug至於這種行爲:

  • 一個常量表達式(5.19),指定具有靜態存儲持續時間的一個完整對象的地址 以及外部或內部鏈接或具有外部或內部鏈接的功能 ,包括函數 模板和函數模板id,但不包括非靜態類成員,表達(忽略括號) 爲& id-表達式,其中id-表達式是對象或函數的名稱,但 &可能如果名稱引用函數或數組,則省略,如果相應的模板參數是引用,則應省略;或

在C++ 14中,它甚至進一步簡化了,甚至沒有提到鏈接。

對於您的具體問題,extern說明符將外部鏈接添加到baz_instance。沒有它,baz_instance有內部鏈接。在C++ 03中,您需要外部鏈接來獲取引用類型的非類型模板參數。在C++ 11中,你不再需要 - 所以extern不再需要,它沒有它就編譯好。

0

extern關鍵字指示該變量是在另一個編譯單元(源文件)中定義的。

你的情況

所以,baz可以在不同的源文件中定義和extern是說這是在這個源文件中定義一個變量的一種方式,但在不同的一個,你會在找到它彙編。

extern關鍵字的意思是「聲明沒有定義」。換句話說,它是一種顯式聲明變量的方法,或者在沒有定義的情況下強制聲明。

+0

從源代碼中可以看出,baz並未在其他源文件中定義。它進一步不會解釋,爲什麼結構實例可以傳遞給外部模板,但不能沒有外部。 – smoes

+0

請參閱我的答案中的編輯 –

1

從14.3.2.1標準狀態:

模板參數的用於非類型的,非模板的模板參數應是以下之一:

  • 對象的地址或功能與外部聯動,包括 功能模板和功能模板id,但不包括非靜態 類成員,表示爲& id-expression其中&是可選項l如果 該名稱指的是函數或數組,或者相應的 模板參數是引用;

https://stackoverflow.com/a/643927/451600通過mweerden

1

extern關鍵字意味着它將具有外部連接,換句話說,當翻譯單元將被編譯的符號將被導出。由於您的類型是常量,因此它默認具有內部鏈接(就像它已被聲明爲static)。模板不能依賴只有內部鏈接的類型。

我很想知道爲什麼,但它似乎失去了時間之沙:Why did C++03 require template parameters to have external linkage?