C++之std::enable_if的实现示例

 更新时间:2026年07月01日 09:12:35   作者:流星雨爱编程  
本文主要介绍了C++之std::enable_if的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.概述

std::enable_if是C++11引入的模板结构体,在VS2019中<xtr1common>文件定义,它的原型是:

template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Test

template <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Test
    using type = _Ty;
};

template <bool _Test, class _Ty = void>
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 <type_traits>
#include <iostream>

template <typename T>
typename std::enable_if <std::is_integral<T>::value, T>::type  addT(T value)
{
	return value + 10;
}

template <typename T>
typename std::enable_if <std::is_floating_point<T>::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 <typename T>
T  addT(T  value, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr)
{
	return value + 10;
}

template <typename T>
T  addT(T value, typename std::enable_if<std::is_floating_point<T>::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 <iostream>
// enabled via a parameter
template<class T>
void destroy(T *,
    typename std::enable_if<std::is_trivially_destructible<T>::value>::type * = 0) {
  std::cout << "destroying trivially destructible T\n";
}
// enabled via a non-type template parameter
template<class T, typename std::enable_if<!std::is_trivially_destructible<T>{} &&
            (std::is_class<T>{} || std::is_union<T>{}),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 <int N>
std::string  tToString(char(&value)[N])
{
	std::string  temp;
	for (int i = 0; i < N; i++) {
		temp += value[i];
	}
	return temp;
}
//2
template <typename T>
std::string  tToString(T value, typename std::enable_if_t<std::is_same_v<T, bool>, T>* = 0) {
	char format[64] = { 0 };
	sprintf(format, "%s", value ? "true" : "false");
	return format;
}
//3
template <typename T>
std::string  tToString(T value, typename std::enable_if_t<std::is_same_v<T, const char*> ||
	std::is_same_v<T, char*> ||
	std::is_same_v<T, std::string>, T>* = 0) {
	return value;
}
//4
template <typename T>
std::string  tToString(T value, typename std::enable_if_t<std::is_integral_v<T> &&
	!std::is_same_v <T, bool>, T>* = 0) { //std::is_integral_v<T>, 整数
	char format[64] = { 0 };
	sprintf(format, "%d", value);
	return format;
}
//5
template <typename T>
std::string  tToString(T value, typename std::enable_if_t<std::is_floating_point_v<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 <typename Integer,
              std::enable_if_t<std::is_integral_v<Integer>, int> = 0
    >
    T(Integer) : m_type(int_t) {}
 
    template <typename Floating,
              std::enable_if_t<std::is_floating_point_v<Floating>, int> = 0
    >
    T(Floating) : m_type(float_t) {} // OK
};
template <typename T, typename Enable = void>
class MyTestClass
{
	// 默认实现,适用于所有类型
public:
	MyTestClass() {
		std::cout << "default";
	}
};

template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_integral<T>::value>::type>
{
	// 整型类型的特化实现
public:
	MyTestClass() {
		std::cout << "int";
	}
};

template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{
	// 浮点型类型的特化实现
public:
	MyTestClass() {
		std::cout << "float";
	}
};
int main()
{
	MyTestClass<std::string>  x1;// OK :匹配初等模板
	MyTestClass<int>  x2;        // OK :匹配偏特化 int 
	MyTestClass<double>  x3;     // OK :匹配偏特化 double
    return 0;
}

参考

std::enable_if - cppreference.com

到此这篇关于C++之std::enable_if的实现示例的文章就介绍到这了,更多相关C++ std::enable_if内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中显示与隐式加载dll的使用与区别

    C++中显示与隐式加载dll的使用与区别

    本文主要介绍了C++中显示与隐式加载dll的使用与区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-12-12
  • C++ primer基础之容器insert

    C++ primer基础之容器insert

    这篇文章主要介绍了C++ primer基础之容器insert的相关资料,需要的朋友可以参考下
    2017-02-02
  • C++/类与对象/默认成员函数@构造函数的用法

    C++/类与对象/默认成员函数@构造函数的用法

    这篇文章主要介绍了C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • Qt实现电子时钟的示例代码

    Qt实现电子时钟的示例代码

    这篇文章主要为大家详细介绍了如何利用Qt实现显示与桌面上并可以随意拖拽至桌面任意位置的电子时钟案例,感兴趣的小伙伴可以尝试一下
    2022-06-06
  • VTK8.1 在 Qt5.9 环境下的配置编译和安装过程

    VTK8.1 在 Qt5.9 环境下的配置编译和安装过程

    为了实现realsense的PCL点云显示,需要VTK支持。由于整个平台在Qt环境实现,VTK编译为Qt插件。整个过程并不复杂,网上的文章大多不全,自己梳理了一下,分享出来,需要的朋友可以参考下
    2022-07-07
  • C语言 scanf的工作原理详解

    C语言 scanf的工作原理详解

    这篇文章主要为大家介绍了C语言 scanf的工作原理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • C语言从代码中加载动态链接库过程解析

    C语言从代码中加载动态链接库过程解析

    这篇文章主要介绍了C语言从代码中加载动态链接库过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • C++简单又轻松建立链式二叉树流程

    C++简单又轻松建立链式二叉树流程

    二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址
    2022-06-06
  • C++对象与继承使用中一些问题介绍

    C++对象与继承使用中一些问题介绍

    大家好,本篇文章主要讲的是C++对象与继承使用中一些问题介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Qt音视频功能实现方法详解

    Qt音视频功能实现方法详解

    音视频应用往往需要大量的计算资源,尤其是在处理高分辨率、高码率的音视频数据时,这篇文章主要给大家介绍了关于Qt音视频功能实现方法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-09-09

最新评论