2010-01-15 126 views
4

我在試着寫一個SFINAE模板來確定兩個類是否可以加在一起。這主要是爲了更好地理解SFINAE是如何工作的,而不是出於任何特定的「真實世界」原因。SFINAE can add template problem

我已經走了這麼得到的是

#include <assert.h> 

struct Vec 
{ 
    Vec operator+(Vec v); 
}; 

template<typename T1, typename T2> 
struct CanBeAdded 
{ 
    struct One { char _[1]; }; 
    struct Two { char _[2]; }; 

    template<typename W> 
    static W make(); 

    template<int i> 
    struct force_int { typedef void* T; }; 

    static One test_sfinae(typename force_int< sizeof(make<T1>() + make<T2>()) >::T); 
    static Two test_sfinae(...); 

    enum { value = sizeof(test_sfinae(NULL))==1 }; 
}; 


int main() 
{ 
    assert((CanBeAdded<int, int>::value)); 
    assert((CanBeAdded<int, char*>::value)); 
    assert((CanBeAdded<char*, int>::value)); 
    assert((CanBeAdded<Vec, Vec>::value)); 
    assert((CanBeAdded<char*, int*>::value)); 
} 

這將編譯所有除了最後一行,這給

finae_test.cpp: In instantiation of ‘CanBeAdded<char*, int*>’: 
sfinae_test.cpp:76: instantiated from here 
sfinae_test.cpp:40: error: invalid operands of types ‘char*’ and ‘int*’ to binary ‘operator+’ 

那麼這個錯誤是一種-的,我期望是什麼,但我希望編譯器然後找到test_sfinae(...)的定義,並使用它,而不是抱怨那個不解析。

顯然我錯過了什麼,我只是不不知道這是什麼。

+3

這是我想出來的。不確定它是否因爲任何明顯的錯誤而失敗:http://codepad.org/VcvIHxhc。會很高興,如果你測試它,並告訴我:) –

+0

@Johannes Schaub:這是一個巨大的努力。要花一段時間來消化。可惜這個SFINAE的東西並不好用。 –

+0

問題是我們還想檢查非類/枚舉類型。那些不會做重載解析,直接進入內置的加法運算符。但是,對於其他對稱運算符,可以重用那個'invalid_list'。而C++ 03不會使無效表達式成爲SFINAE失敗,因此對於簡單代碼,我們將不得不等待C++ 0x。 –

回答

4

它在我看來像你遇到了在Core Issue 339以及N2634討論的問題。最重要的是,即使你正在做的是被標準允許的,你仍然在推動任何編譯器當前可以處理的內容。 C++ 0x將添加更多關於什麼會導致SFINAE失敗與導致硬錯誤的細節。請參閱N3000,第14.9.2節,如果你想進入血淋淋的細節。