我想编写一个 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;

它接缝没有任何模板有效,但我没有从编译器那里得到任何提示,为什么这两种特化都失败了。

最佳答案

专业必须与主要专业相匹配。确定 X<AA> 是什么的查找规则是首先匹配主要类型并添加默认类型,这使我们得到 X<AA, void> ,然后尝试将其与所有特化匹配。但是您的专业都与 X<AA, void> 不匹配,因此您最终获得了主要专业。主要不是一个完整的类型,因此是错误的。

为什么它们都不匹配?因为你写道:

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

对于评估为 AAint ,它与 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 - 所以它也不匹配。

关于c++ - SFINAE 专业类(class),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37280531/

10-09 13:41