2016-05-17 46 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 - 因此它太不匹配。