2009-02-10 45 views
4

這裏的原標題是 解決方法在VS2005çSFINAE錯誤++使用SFINAE檢測在C型++

這是試探性的使用SFINAE的,以便爲is_pod模板類相當於POD岬那存在於TR1中(在VS2005中還沒有TR1)。當模板參數是一個POD類型(包括使他們的基本類型和結構)和假時,它不是(像非平凡的構造函數)它應該有它的價值成員真。

template <typename T> class is_pod 
{ 
    public: 

    typedef char Yes; 
    typedef struct {char a[2];} No; 

    template <typename C> static Yes test(int) 
    { 
     union {T validPodType;} u; 
    } 
    template <typename C> static No test(...) 
    { 
    } 
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))}; 
}; 

class NonPOD 
{ 
    public: 
    NonPod(const NonPod &); 
    virtual ~NonPOD(); 
}; 

int main() 
{ 
    bool a = is_pod<char>::value; 
    bool b = is_pod<NonPOD>::value; 
    if (a) 
    printf("char is POD\n"); 
    if (b) 
    printf("NonPOD is POD ?!?!?\n"); 
    return 0; 
} 

的問題是,不僅VS 2005沒有TR1,也不會在乎上面的工會(當模板參數不是POD應該是無效的),這樣既和b評估爲真。


感謝您選擇以下答案。仔細閱讀了他們(和代碼)後,我意識到我正在嘗試做的實際上是一種錯誤的方法。當時的想法是SFINAE行爲與適應相結合,模板must_be_pod(我在書中不完善C++發現,但它可以在其他地方找到,太)。實際上,這需要一套非常特別的SFINAE規則,顯然這不是標準定義的。畢竟,這不是VS中的一個錯誤。

回答

4

與方法最大的問題是你不這樣做SFINAE這裏 - SFINAE僅適用於參數類型,在這裏返回類型。

然而,在標準的所有SFINAE情況下,沒有適用於您的情況。它們是空隙,參考文獻,功能或無效大小的

  • 型部件的

    • 陣列不是一個類型
    • 指針的引用,引用的引用,引用的孔隙
    • 指針構件非類類型的
    • 模板值的無效轉化參數
    • 功能類型的具有空隙類型的參數
    • 常量/ volati樂功能型

    這可能是爲什麼Boost文檔中,有:

    沒有一些(如尚未明確的)幫助 從編譯器,ispod永遠 報告類或結構是一個 POD;這總是安全的,如果可能的話 次優。目前(2005年5月)只有 MWCW 9和Visual C++ 8有 必要的編譯器_intrinsics。

  • 1

    我不確定您在這裏嘗試使用SFINAE的方式,因爲is_pod<T>::test(...)也會匹配is_pod<T>::test(0)。或許,如果你使用一個不同的類型,而不是「廉政」,你會得到更好的匹配:

    template <typename T> class is_pod 
    { 
        struct my_special_type { }; 
        public: 
        typedef char Yes; 
        typedef struct {char a[2];} No; 
    
        template <typename C> static Yes test(my_special_type) 
        { 
         union {T validPodType;} u; 
        } 
    
        template <typename C> static No test(...) 
        { 
        } 
        enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))}; 
    }; 
    

    你可能也想看看Boost.Enable_i F到做你SFINAE你 - 除非你試圖實施自己的圖書館或出於某種原因。

    +0

    我試圖用char *來使用另一種類型,而不是你所建議的空的結構,但無濟於事。我只是試圖用你的例子,但它給出了相同的結果(對於POD和非POD都是這樣)。 – 2009-02-10 23:35:35

    2

    這並不與VS2008工作,要麼,但我懷疑你知道這一點。 SFINAE用於推導模板參數的模板參數;即使您可以創建與另一種類型不兼容的類型(即,聯合不能使用非POD),您也無法真正推斷出某種類型的構造函數的類型。

    事實上,VS 2008使用的編譯器支持的特徵來實現std::tr1::type_traits