遇到了enable_if问题以及相关的概念,这里做一下总结;
基本概念:
enable_if
主要的作用是模板类型推导,用于选择重载的版本;
这里先说一下SFINAE,因为enable_if
所用的也是SFINAE特性;
1.SFINAE概念:
全称为:Sbusitution Failure Is Not An Error;
用人话说的意思就是,如果有多个重载函数,不能匹配的重载函数看作删除,而不作为错误;
在重载时,会先利用该参数进行所有候选函数的推导,来得到一个完美的匹配;
但是对于不能匹配的无效模板参数,则会从重载决意集合中删除,而不是报错;
2.enable_if作用:
enable_if
更多的可以看作一种swtich选择条件,源码如下所示:
// STRUCT TEMPLATE enable_if
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Test
template <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Test
using type = _Ty;
};
总的来书也是模板泛化,但是包含普适和特例两种情况;
接受两个模板参数,判断条件_test
布尔值,_Ty
类型值;
可以看到,由于特例化的存在,只有当_test
为真时,内部才有type
,否则使用enable_if<T1,T2>::type
为未定义类型;
再提一下typename的问题;
typename 可以视为class的拓展,但是不局限于使用在template声明中,而是可以告知某个变量是类型还是类内成员;
例如:
template<typename T>
void fun(const T& proto){
T::const_iterator it(proto.begin());
}
上述代码并不能通过编译,根本原因是不能分辨T::const_iterator是类型还是类内成员;
因此需要在前面加上:
typename T::const_iterator it(proto.begin());
告知编译器T::const_iterator是一个类型,而非类内成员,it则是该类型下的声明的一个变量;
具体例子:
这里参照网上和书本示例:
template<typename T>
typename std::enable_if<std::is_integral<T>::value,T>::type ret(T k) {
cout << "this is int type" << endl;
return k;
}
template<typename T>
typename std::enable_if<std::is_same<T, double>::value, T>::type ret(T k) {
cout << "this is double version" << endl;
return k;
}
上段代码定义了ret()
函数的两个版本;
第一个为int版本,第二个为double版本;
注意一下内部的判断bool泛型:is_integral<T>
、is_same<T,U>
;
前者判断是否为int,后者判断泛型型别是否相同;
typename std::enable_if<condition,T>::type ret(T k) {
return k;
}
enable_if
可以根据T的类型进行判断,从而选择和自己类型指定的重载函数;