others - 通過typedef強制模板實例化: 在G 上成功,在Visual C 上失敗

113 5

我想強制模板實例化,
下面的代碼在g (http://coliru.stacked-crooked.com/a/33986d0e0d320ad4 )處運行(列印出1 ),
但是,它在Visual C (https://rextester.com/WGQG68063 )輸出錯誤的結果(0 )。


#include <iostream>


#include <string>


template <int& T>struct NonTypeParameter { };



//internal implementation


int lala=0;


template <typename T> struct Holder{


 static int init;


};


template <typename T> int Holder<T>::init = lala++;



//tool for user 


template <typename T> struct InitCRTP{ 


 using dummy=NonTypeParameter<Holder<T>::init>;


};



class WantInit : public InitCRTP<WantInit>{};//user register easily


int main(){


 std::cout << lala << std::endl;


}



是Visual C++編譯器錯誤,還是一種未定義的行為?
如果是Visual C 錯誤,如何解決它的?

时间: 原作者:

135 1

編譯器錯誤,當然我們可以通過修改InitCRTP來驗證它:


template <typename T, typename = NonTypeParameter<Holder<T>::init>>


struct InitCRTP {


};



引用InitCRTP這又應該強制Holder<T>::init的實例化,但是vs沒有實例化

我們可以進一步驗證,當用作基類時,成員函數聲明與類一起被實例化:


template <typename T> struct InitCRTP{


 using dummy=NonTypeParameter<Holder<T>::init>;


 void dummy2(dummy);


};



儘管如此,VC還是出現了錯誤,鑒於Clang和GCC都表現出的行為,所以,這是一個VC錯誤。

原作者:
131 4

class WantInit : public InitCRTP<WantInit>不是實例化InitCRTP<WantInit>::dummy,也不是Holder<WantInit>::init,因為它們不是由程序中實際使用的某些東西引用的,代碼中的隱式實例化鏈不需要實例化Holder<T>::init,請參見隱式實例化

這適用於類模板的成員: 除非該成員在程序中使用否則它不被實例化並且不需要定義。

修復是使用顯式模板實例化


template struct Holder<void>;



這會導致Holder<void>與它的所有非模板成員一起被實例化。

或者,你也可以只實例化Holder<T>::init成員,例如:


static_cast<void>(Holder<void>::init);



原作者:
58 0

讓我們試著確定ODR-use的成員。


#include <iostream>


#include <string>



int lala=0;


template <typename T> struct Holder{


 static int init;


};


template <typename T> int Holder<T>::init = lala++;



template <typename T> struct InitCRTP{


 InitCRTP() { (void)Holder<T>::init; }


};



class WantInit : public InitCRTP<WantInit>{};


int main(){


 std::cout << lala << std::endl;


 // WantInit w; <---------------------------- look here


}



現在,如果註釋掉的行被註釋掉,程序的結果就會改變。

原作者:
...