SFINAE, 全称为"匹配失败并不是一种错误(Substitution Failure Is Not An Error). 这个源码看着还是有点费劲的!先举个例子。
template<typename T, bool C = true>
struct if_ {
static const int value = 1;
};
template<typename T>
struct if_<T, true> {
static const int value = 2;
};
int main() {
printf("value: %d\n", if_<int>::value);
}
这里肯定选特化的版本,输出是2。类模板可以具有
类型
或
值形参
的默认实参。 使用等号 (=) 后跟类型名称或值来指定默认参数。因为值形参C默认是true,不显式指定的情况下就是true。相当于:
template<typename T, bool C = true>
struct if_ {};
template<typename T>
struct if_<T, false> {
static const int value = 1;
};
template<typename T>
struct if_<T, true> {
static const int value = 2;
};
int main() {
printf("value: %d\n", if_<int>::value);
}
下面,来看另一个例子!首先来一个判断类型是基本类型还是类类型的模板类。
template <typename T>
class is_class {
template <typename U>
static char helper(int U::*);
template <typename U>
static int helper(...);
public:
static const bool value = sizeof(helper<T>(0)) == 1;
};
最后是is_base_of出场:
template <typename T1, typename T2>
struct is_same {
static const bool value = false;
};
template <typename T>
struct is_same<T, T> {
static const bool value = true;
};
template<typename Base, typename Derived, bool = (is_class<Base>::value && is_class<Derived>::value)>
class is_base_of {
template <typename T>
static char helper(Derived, T);
static int helper(Base, int);
struct Conv {
operator Derived();
operator Base() const;
};
public:
static const bool value = sizeof(helper(Conv(), 0)) == 1;
};
template <typename Base, typename Derived>
class is_base_of<Base, Derived, false> {
public:
static const bool value = is_same<Base, Derived>::value;
};
template <typename Base>
class is_base_of<Base, Base, true> {
public:
static const bool value = true;
};
然后还看有人像下面这么实现,简单的让我不敢相信,没严格测试,不知道是否够健壮!原理就是:派生类可以隐式转化为基类!如果转换成功,就用非模板形式,返回true,反之,返回false!
template<typename T>
class CTestBase{
public:
static bool testbase(const T&){return true;}
template<typename U>
static bool testbase(U&){return false;}
};
template<typename T1, typename T2>
bool is_base_of(){
return CTestBase<T1>::testbase(T2());
}
template<typename T1, typename T2>
bool instanceof(const T2&){
return CTestBase<T1>::testbase(T2());
}
注意做实参的T2()后面的这个括号,这就是用默认构造函数生成的无名临时对象了,不是类型。