- enable_if 的主要作用就是当某个 condition 成立时,enable_if可以提供某种类型.
- 其作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中。它的定义也异常的简单:
template <bool, typename T=void>
struct enable_if {
};
template <typename T>
struct enable_if<true, T> {
using type = T;
};
从上面的代码可以看到,在 condition 为真的时候,由于偏特化机制,第二个结构体模板明显是一个更好的匹配,所以 std::enable_if<>::type 就是有效的。当 condition 为假的时候,只有第一个结构体模板能够匹配,所以 std::enable_if<>::type 是无效的,会被丢弃。
所以,只有当第一个模板参数为 true 时,type 才有定义,否则使用 type 会产生编译错误,并且默认模板参数可以让你不必指定类型。
示例
// enable_if example: two ways of using enable_if
#include <iostream>
#include <type_traits>
// 1. the return type (bool) is only valid if T is an integral type:
template <class T>
typename std::enable_if<std::is_integral<T>::value,bool>::type //返回仅当类型为整形
is_odd (T i) {return bool(i%2);}
// 2. the second template argument is only valid if T is an integral type:
template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}
int main() {
short int i = 1; // code does not compile if type of i is not integral;如果 inr为非整型,代码不会编译; std::cout << std::boolalpha;
std::cout << "i is odd: " << is_odd(i) << std::endl;
std::cout << "i is even: " << is_even(i) << std::endl;
return 0;
}
下面说说它的几种使用方法
用法二:控制函数返回类型
通过模板参数类型推演,可见从形参类型和返回值类型相同,也可以理解为根据不同的实参类型实例化不同的实参类型返回值
template <std::size_t k, class T, class... Ts>
typename std::enable_if<k==0, typename element_type_holder<0, T, Ts...>::type&>::type
get(tuple<T, Ts...> &t) {
return t.tail;
}
template <std::size_t k, class T, class... Ts>
typename std::enable_if<k!=0, typename element_type_holder<k, T, Ts...>::type&>::type
get(tuple<T, Ts...> &t) {
tuple<Ts...> &base = t;
return get<k-1>(base);
}
由于函数模板不能偏特化,通过 enable_if 便可以根据 k 值的不同情况选择调用哪个 get,进而实现函数模板的多态。