C++之std::enable_if

相关系列文章

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.作为类模板或函数模板参数


1.概述

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)作为类模板或函数模板参数,控制不同的数据类型,选择不同的类模板或函数模板

下面就举例一一用示例说明它们的具体用法

2.函数返回值场景

#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;
}

3.函数参数场景

示例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;
}

4.作为类模板或函数模板参数

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

你可能感兴趣的:(#C++进阶,c++,开发语言)