SFINAE专业班

时间:2016-05-17 15:32:02

标签: c++ c++14 sfinae

我想写一个template class来检查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;

它表明没有任何模板可以正常工作,但我没有从编译器那里得到任何特殊化失败的提示。

1 个答案:

答案 0 :(得分: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的{​​{1}},与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 - 因此它也不匹配。