Substitution failure is not an error(SFINAE) :匹配失败不是错误
真是晦涩的一句话啊。。。
匹配重载的函数/类时如果匹配后会引发编译错误,这个函数/类就不会作为候选。
这是一个 C++11 的新特性,也是 enable_if 最核心的原理。
最关键是 enable_if 的用法
查到 API 说明
template <bool Cond, class T = void> struct enable_if;
Enable type if condition is met
The type T is enabled as member type enable_if::type if Cond is true.
Otherwise, enable_if::type is not defined.
This is useful to hide signatures on compile time when a particular condition is not met, since in this case, the member enable_if::type will not be defined and attempting to compile using it should fail.
It is defined with a behavior equivalent to:
template<bool Cond, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };
简单来说就是 Cond 这个参数为true时,模板匹配就能成功,否则失败;
#include <type_traits>
#include <iostream>
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value,void>::type>
bool isodd(T num)
{
return num % 2;
}
int main()
{
std::cout << isodd(2) << std::endl;
//传入的参数类型不是整型,模板匹配失败
//std::cout << isodd(2.0) << std::endl;
return 0;
}
还可以匹配指针类型的
#include <type_traits>
#include <iostream>
template<typename T, typename = typename std::enable_if<std::is_pointer<T>::value , void>::type>
void pointer_test(T)
{
std::cout << "input is pointer..." << std::endl;
}
int main()
{
char* pCh = nullptr;
pointer_test(pCh);
return 0;
}
说到指针,想到类型推导函数 decltype
int main()
{
int a[10] = { 9 };
decltype(*a) b = a[0];
std::cout << a[0] << std::endl;
b = 0;
std::cout << a[0] << std::endl;
return 0;
}
从输出可以看到改变 b 的值就是在改变 a[0] 的值;因为 decltype(*a) 推导出来的类型为 int&; 怎么去除这种引用呢?
remove_reference
//将上面代码的类型推导改成这样即可
std::remove_reference<decltype(*a)>::type b = a[0];
那么 std::remove_reference 做了啥?
直接看源代码如下:
template <class _Ty>
struct remove_reference {
using type = _Ty;
using _Const_thru_ref_type = const _Ty;
};
template <class _Ty>
struct remove_reference<_Ty&> {
using type = _Ty;
using _Const_thru_ref_type = const _Ty&;
};