相关系列文章
C++之std::is_object
C++之std::decay
C++模板函数重载规则细说
C++之std::declval
C++之std::move(移动语义)
C++之std::forward(完美转发)
C++之std::enable_if
C++之std::is_pod(平凡的数据)
目录
1.概述
2.函数返回值场景
3.函数参数场景
4.作为类模板或函数模板参数
std::enable_if是C++11引入的模板结构体,在VS2019中
template
struct enable_if {}; // no member "type" when !_Test
template
struct enable_if { // type is _Ty for _Test
using type = _Ty;
};
template
using enable_if_t = typename enable_if<_Test, _Ty>::type;
_Test如果是true, std::enable_if的type为_Ty;如果是false, type没有定义,这种情况在程序编译的时候就会报错,此元函数是活用 SFINAE ,基于类型特性条件性地从重载决议移除函数,并对不同类型特性提供分离的函数重载与特化的便利方法。 std::enable_if 可用作额外的函数参数(不可应用于运算符重载)、返回类型(不可应用于构造函数与析构函数),或类模板或函数模板形参。
因此std::enable_if可以以多种形式使用,它的作用主要有:
1)通过函数的返回值,控制不同的条件下,选择不同的模板
2)通过函数的参数,控制不同的条件下,选择不同的模板
3)作为类模板或函数模板参数,控制不同的数据类型,选择不同的类模板或函数模板
下面就举例一一用示例说明它们的具体用法
#include
#include
template
typename std::enable_if ::value, T>::type addT(T value)
{
return value + 10;
}
template
typename std::enable_if ::value, T>::type addT(T value)
{
return value + 5.0;
}
int main()
{
int d = 10;
double f = 20;
d = addT(d); //d = 20
f = addT(f); //f = 25.000000000
return 0;
}
示例1:
template
T addT(T value, typename std::enable_if::value, T>::type* = nullptr)
{
return value + 10;
}
template
T addT(T value, typename std::enable_if::value, T>::type* = nullptr)
{
return value + 5;
}
int main()
{
int d = 10;
double f = 20;
d = addT(d);
f = addT(f);
return 0;
}
示例2:
#include
// enabled via a parameter
template
void destroy(T *,
typename std::enable_if::value>::type * = 0) {
std::cout << "destroying trivially destructible T\n";
}
// enabled via a non-type template parameter
template{} &&
(std::is_class{} || std::is_union{}),bool>::type = true>
void destroy(T* t)
{
std::cout << "destroying non-trivially destructible T\n";
}
int main() {
int nValue = 1;
std::string test = "hell";
destroy(&nValue);
destroy(&test);
return 0;
}
输出如下:
destroying trivially destructible T
destroying non-trivially destructible T
示例3:
利用sprintf把数字或字符串转换为std::string, 根据格式化的不同,就用std::enable_if控制调用不同的转换函数,代码如下:
//1
template
std::string tToString(char(&value)[N])
{
std::string temp;
for (int i = 0; i < N; i++) {
temp += value[i];
}
return temp;
}
//2
template
std::string tToString(T value, typename std::enable_if_t, T>* = 0) {
char format[64] = { 0 };
sprintf(format, "%s", value ? "true" : "false");
return format;
}
//3
template
std::string tToString(T value, typename std::enable_if_t ||
std::is_same_v ||
std::is_same_v, T>* = 0) {
return value;
}
//4
template
std::string tToString(T value, typename std::enable_if_t &&
!std::is_same_v , T>* = 0) { //std::is_integral_v, 整数
char format[64] = { 0 };
sprintf(format, "%d", value);
return format;
}
//5
template
std::string tToString(T value, typename std::enable_if_t, T>* = 0) { //浮点数
char format[64] = { 0 };
sprintf(format, "%f", value);
return format;
}
int main()
{
std::string f = tToString(true); //调用 2 版本函数
f = tToString(100); //调用 4 版本函数
f = tToString("43634636"); //调用 3 版本函数
f = tToString(88.4444); //调用 5 版本函数
f = tToString(std::string("435236236")); //调用 3 版本函数
char testT[] = "35353535345";
f = tToString(testT); //调用 1 版本函数
char* pTest = testT;
f = tToString(pTest); //调用 3 版本函数
const char* pTest1 = "ntrnrtnr44";
f = tToString(pTest1); //调用 3 版本函数
return 0;
}
struct T {
enum { int_t,float_t } m_type;
template , int> = 0
>
T(Integer) : m_type(int_t) {}
template , int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};
template
class MyTestClass
{
// 默认实现,适用于所有类型
public:
MyTestClass() {
std::cout << "default";
}
};
template
class MyTestClass::value>::type>
{
// 整型类型的特化实现
public:
MyTestClass() {
std::cout << "int";
}
};
template
class MyTestClass::value>::type>
{
// 浮点型类型的特化实现
public:
MyTestClass() {
std::cout << "float";
}
};
int main()
{
MyTestClass x1;// OK :匹配初等模板
MyTestClass x2; // OK :匹配偏特化 int
MyTestClass x3; // OK :匹配偏特化 double
return 0;
}
参考
std::enable_if - cppreference.com