2016-05-17 57 views
4

我想寫一個template class檢查與SFINAE性狀。專業班與SFINAE

如類不能 「超載」 我在那個帖子寫着:template overloading and SFINAE working only with functions but not classes

我寫了下面的代碼:

class AA { public: using TRAIT = int; }; 
class BB { public: using TRAIT = float; }; 

template < typename T, typename UNUSED = void> class X; 

template < typename T> 
class X<T, typename std::enable_if< std::is_same< int, typename T::TRAIT>::value, int >::type> 
{ 
    public: 
     X() { std::cout << "First" << std::endl; } 
}; 

template < typename T> 
class X<T, typename std::enable_if< !std::is_same< int, typename T::TRAIT>::value, unsigned int >::type> 
{ 
    public: 
     X() { std::cout << "Second" << std::endl; } 
}; 

int main() 
{ 
    X<AA> a; 
    X<BB> b; 
} 

但它只是失敗:

error: aggregate 'X<AA> a' has incomplete type and cannot be defined 
     X<AA> a; 
      ^

error: aggregate 'X<BB> b' has incomplete type and cannot be defined 
     X<BB> b; 

它認爲沒有一個模板可以工作,但我沒有從編譯器得到任何暗示,說明爲什麼兩個專業化都失敗了。

回答

6

專長必須與主要匹配。用於確定X<AA>的查找規則是首先匹配主要並添加默認類型,這會使我們獲得X<AA, void>,然後嘗試將其與所有專業化匹配。但是沒有一個專業匹配X<AA, void>,所以你最終得到的主要。主要不是一個完整的類型,因此是錯誤。

爲什麼它們都不匹配?因爲你寫道:

typename std::enable_if< std::is_same< int, typename T::TRAIT>::value, int >::type 

對於AA該演算值爲爲int,這不符合void,所以專業化不考慮。你只是想:

typename std::enable_if< std::is_same< int, typename T::TRAIT>::value>::type 

或真:

std::enable_if_t< std::is_same< int, typename T::TRAIT>::value> 

同樣,對於BB,第二專業化的第二種類型的計算結果爲unsigned int而不是void - 因此它太不匹配。