SFINAE的专业课
Specializing class with SFINAE
我想写一个template class
,它用SFINAE检查特征。
正如我在那篇文章中所读到的那样,类不能"重载":模板重载和SFINAE只能处理函数,而不能处理类
我写了以下代码:
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
对于评估为int
的AA
,它与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
,因此它也不匹配。
相关文章:
- 为什么使用SFINAE而不是函数重载
- 如何使用模板函数的函数签名进行SFINAE
- 数据成员SFINAE的C++17测试:gcc vs clang
- 使用在用于SFINAE的void_t中具有参数的方法
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 提供与TMP和SFINAE的通用接口
- "Inverse SFINAE"避免模棱两可的过载
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 如何在儿童类中使用SFINAE
- 使用 SFINAE 作为模板参数的编译时递归
- 使用 SFINAE 设计模板方法
- 与SFINAE支票交朋友
- C++许多 SFINAE 风格的过载
- 是否可以混合使用SFINAE和模板专业化?
- C++表达SFINAE和ostream操纵器
- SFINAE不能防止模棱两可的操作员过载吗?
- SFINAE是否取决于类型推断?
- MSVC 无法编译 SFINAE 检查
- SFINAE 检查模板参数运算符
- SFINAE的专业课