2016-08-10 59 views
1

它看起來像編譯器接受不同的語法來初始化模板中的靜態。模板專業化靜態初始化icc + vc vs gcc + clang

template <typename T> struct TBase 
{ 
    static const int i; 
    static const int j; 
}; 

// compile: gcc + clang + visual + icc 
template <> const int TBase<double>::i=1; 

// compile: vc + icc 
// failed gcc, gcc -fpermissive, clang 
const int TBase<double>::j=2; 

而不template<>由標準接受的語法,即使它顯然不是便攜式的時刻?

編輯: 使用此代碼vC++ TBase<double>::i==1TBase<double>::j==2完全像沒有模板的代碼。

struct noTemplate 
{ 
    static const int i; 
    static const int j; 
}; 
const int noTemplate::i=1; 
const int noTemplate::j=2; 

gcc和鐺似乎強制使用的template<>初始化這個靜態的,我不明白爲什麼編譯器需要這些信息。

回答

3

兩個語法都是有效的,但它們意味着不同的事情。與template<>語法用來聲明或定義的隱式或顯式實例的成員:

template<class T> struct X { static int const i; }; 

template<> int const X<char>::i = 1; // Define member of an implicit instantiation 

template struct X<long>; 
template<> int const X<long>::i = 2; // Define member of an explicit instantiation 

而不template<>語法用於定義一個專業化的成員:

template<> struct X<float> { static int const j; }; // Class template specialization 
int const X<float>::j = 3; 
+0

謝謝。所以隱式實例化是針對模板本地使用的,顯式實例化針對模板導出,就像在lib中一樣。用vC++模板聲明並初始化一個值,如int const X :: j = 3;代碼(x ())就足夠了,j爲「有效」似乎有點奇怪。 – ColdCat

0

是的,它似乎符合標準。至少C++ 14標準包含(希望它的最終版本也包含它,我已經檢查過預發佈版本http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf)。

14.7.1隱式實例 ... 除非類模板或成員模板的成員已明確實例化或明確專業化,當專業化的被引用的成員的專業化隱式實例要求成員定義存在的上下文;特別是靜態數據成員的初始化(以及任何相關的副作用)不會發生,除非靜態數據成員本身以需要靜態數據成員定義存在的方式使用。 ...

通過const int TBase<double>::j=0;您正在訪問(不專業)靜態成員的TBase<double>j,所以TBase<double>專業化應該如果尚未存在的創建。

的代碼示例沒有模板,這證明你只是訪問結構成員:

struct WithoutTemplate { 
    static const int i; 
}; 
const int WithoutTemplate::i = 5; 
+0

謝謝,我更新了我的問題,強調了我的審問。 – ColdCat