c++模板元编程std::enable_if详解
std::enable_if 概述
// Primary template.
/// Define a member typedef @c type only if a boolean constant is true.
template<bool, typename _Tp = void>
struct enable_if
{ };
// Partial specialization for true.
template<typename _Tp>
struct enable_if<true, _Tp>
{ typedef _Tp type; };
结合源码看,只有第一个模板参数为true时,struct 才会定义一个public的type类型(struct成员默认是public类型),type即为第二个模板参数。
使用场景
类型偏特化
在使用模板编程的时候,可以使用enbale_if的特性根据模板参数的不同特性进行不同的类型选择。
template<class T, class Enable = void>
class Test {
public:
Test() {
std::cout << "normal template" << std::endl;
}
};
template<class T>
class Test<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
public:
Test() {
std::cout << "is_floating_point" << std::endl;
}
};
int main() {
auto a1 = std::make_shared<Test<int>>();
auto a2 = std::make_shared<Test<float>>();
return 0;
}
执行结果:
normal template
is_floating_point
控制函数返回值
通过函数的返回值,在不同的条件下,选择不同的模板。
template <typename T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
GetValue (T i) {
cout << "is integral" << endl;
return i>0;
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value,bool>::type
GetValue (T i) {
cout << "is not integral" << endl;
return i>0;
}
int main()
int i = 1;
float f = 2.0;
std::cout << i << " GetValue : " << GetValue(i) << std::endl;
std::cout << f << " GetValue : " << GetValue(f) << std::endl;
return 0;
}
执行结果:
1 GetValue : is integral
1
2 GetValue : is not integral
1
函数参数场景
通过函数的参数,在不同的条件下,选择不同的模板。
template <typename T,
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void TestFunc(T msg) {
std::cout << "is integral" << std::endl;
}
template <typename T,
typename std::enable_if<!std::is_integral<T>::value, int>::type = 0>
void TestFunc(T msg) {
std::cout << "is not integral" << std::endl;
}
执行结果:
is integral
is not integral
另外这块的详细使用场景也可以看下百度apollo cyber代码中message部分的封装,也是大量使用了std::enable_if。