std::enable_if 顾名思义,满足条件时类型有效。作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程中。它的定义也非常的简单:

// STRUCT TEMPLATE enable_if
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Testtemplate <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Testusing type = _Ty;
};

由此可知,只有当第一个模板参数_Testtrue 时,type 才有定义(type即第二个模板参数_Ty);否则使用 type 会产生编译错误,且默认模板参数可以让你不必指定类型。

另外enable_if_t是一个别名,其定义如下:

template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;

std::enable_if可以用作函数参数、返回类型或类模板或函数模板参数,以有条件地从重载中删除函数或类。

一、作为函数参数

template<typename T>
struct Check1
{//如果T的类型是int,则定义函数 int read(void* = nullptr)template<typename U = T>U read(typename std::enable_if_t<std::is_same_v<U, int> >* = nullptr) {return 42;}//如果T的类型是double,则定义函数 double read(void* = nullptr)template<typename U = T>U read(typename std::enable_if_t<std::is_same_v<U, double> >* = nullptr) {return 3.14;}
};

使用示例

Check1<int> c1;
int x1 = c1.read();Check1<double> c2;
double x2 = c2.read(0);

二、作为模板参数

template<typename T>
struct Check2
{//如果T的类型是int,则定义函数 int read()template<typename U = T, typename std::enable_if_t<std::is_same_v<U, int>, int> = 0>U read() {return 42;}//如果T的类型是double,则定义函数 double read()template<typename U = T, typename std::enable_if_t<std::is_same_v<U, double>, int> = 0>U read() {return 3.14;}
};

也可以写成如下形式:

template<typename T>
struct Check2
{template<typename U = T, typename std::enable_if_t<std::is_same_v<U, int>>* = nullptr>U read() {return 42;}template<typename U = T, typename std::enable_if_t<std::is_same_v<U, double>>* = nullptr>U read() {return 3.14;}
};

三、作为返回值类型

对于模板函数,有时希望根据不同的模板参数返回不同类型的值。

template<typename T>
struct Check3
{//如果T的类型是int,则定义函数 int read()template<typename U = T>typename std::enable_if_t<std::is_same_v<U, int>, U> read() {return 42;}//如果T的类型是double,则定义函数 double read()template<typename U = T>typename std::enable_if_t<std::is_same_v<U, double>, U> read() {return 3.14;}
};

利用auto关键字,可以写为如下形式:

// int goo<true>(int x)
template<bool B>
auto goo(int x) -> std::enable_if_t<B, int>
{return 1;
}// int goo<false>(int x)
template<bool B>
auto goo(int x) -> std::enable_if_t<!B, int>
{return 2;
}

四、类型偏特化

在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。例如:

// T是其它类型
template<typename T, typename = void>
struct zoo;// 如果T是浮点类型
template<typename T>
struct zoo<T, std::enable_if_t<std::is_integral_v<T>>>
{};

五、concepts

C++20中利用concepts可以简化编写方式:

#ifdef __cpp_lib_concepts
#include <concepts>
#endif// 如果T是整数类型
template<std::integral T>
void display_concepts_1(T num)
{}// 如果T是整数类型
void display_concepts(std::integral auto num)
{}// 如果T是浮点数类型
void display_concepts(std::floating_point auto num)
{}

等价于如下形式:

// 如果T是整数类型
template<typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
void display_1(T num)
{}// 如果T是整数类型
template<typename T>
void display(typename std::enable_if_t<std::is_integral_v<T>>* = nullptr)
{}// 如果T是浮点数类型
template<typename T>
void display(typename std::enable_if_t<std::is_floating_point_v<T>>* = nullptr)
{}

C++11模板元编程—std::enable_if使用说明相关推荐

  1. 基于C++11模板元编程实现Scheme中的list及相关函数式编程接口

    前言 本文将介绍如何使用C++11模板元编程实现Scheme中的list及相关函数式编程接口,如list,cons,car,cdr,length,is_empty,reverse,append,map ...

  2. C++11模版元编程的应用

    1.概述 关于C++11模板元的基本用法和常用技巧,我在程序员2015年2月B<C++11模版元编程>一文(后称前文)中已经做了详细地介绍,那么C++11模版元编程用来解决什么实际问题呢, ...

  3. 【C++ 泛型编程 进阶篇】:用std::integral_constant和std::is_*系列深入理解模板元编程

    C++ 元模版编程:用std::integral_constant和std::is_*系列深入理解模板元编程 一.模板元编程与类型特性 (Template Metaprogramming and Ty ...

  4. 现代C++模板元编程基础

    元函数的基础介绍 C++的模板元编程是函数式编程,所以函数是一等公民.一切在编译期间执行的函数都可以称为元函数.元函数有struct和constexpr两种定义方式,前者是一直使用的,后者是C++11 ...

  5. 模板元编程实现素数判定

    模板元编程(英语:Template metaprogramming:缩写:TMP)是一种元编程技术,不夸张的说,这项技术开启了一种新的C++编程方式.编译器使用模板产生暂时性的源码,然后再和剩下的源码 ...

  6. C++ 模板元编程简介

    文章目录 1.概述 2.模板元编程的作用 3.模板元编程的组成要素 4.模板元编程的控制逻辑 4.1 if 判断 4.2 循环展开 4.3 switch/case 分支 5.特性.策略与标签 6.小结 ...

  7. 闭关之 C++ 函数式编程笔记(四):monad 和 模板元编程

    目录 第十章 monad 注意 10.1 仿函数并不是以前的仿函数 10.1.1 处理可选值 10.2 monad: 更强大的仿函数 10.3 基本的例子 10.4 range 与 monad 的嵌套 ...

  8. C++高阶必会操作--模板元编程

    泛型编程大家应该都很熟悉了,主要就是利用模板实现"安全的宏",而模板元编程区别于我们所知道的泛型编程,它是一种较为复杂的模板,属于C++的高阶操作了,它最主要的优点就在于把计算过程 ...

  9. C++模板元编程详细教程(之五)

    前序文章请看: C++模板元编程详细教程(之一) C++模板元编程详细教程(之二) C++模板元编程详细教程(之三) C++模板元编程详细教程(之四) STL中提供的工具 从这一篇开始,我们将正式介绍 ...

最新文章

  1. 相机原理updateTexImage
  2. c语言节点有指针域数据域,学习心得:链表的操作(C语言实现)
  3. linux vnc 屏幕大小,Linux系统下vnc 的配置和使用方法
  4. @getmapping注解的作用_一口气说出6种,@Transactional注解的失效场景
  5. thinkcmf 横向排列数据_利用python进行数据分析之数据清洗规整
  6. [vue] 你知道style加scoped属性的用途和原理吗?
  7. java质数判断程序_java判断一个数是否为素数/质数
  8. MediaPlayer控件的初探
  9. (转)RabbitMQ学习之安装
  10. 腾讯拟全资收购搜狗;英特尔人事大变动,首席工程官将离职;TensorFlow 2.3.0 正式发布 | 极客头条
  11. php中array_flip数组翻转
  12. python queue的用法_PYTHON多进程用法之四(Queue)
  13. android视频添加特效,抖音蝴蝶翅膀特效怎么弄的 安卓手机上给视频加蝴蝶特效的方法...
  14. 【MySQL】黑马教程MySQL数据库 MySQL基础(二)
  15. 你应该怎么样活着才有意思
  16. Elasticsearch系列—倒排索引原理
  17. 百度图片批量下载助手
  18. 将swolidwroks文件导出URDF,导入v-rep\CoppeliaSim
  19. 人生感悟:欲望适度则为利,欲望过度则为害,高级java开发工程师简历
  20. 設計模式之Visitor

热门文章

  1. 『david_lv』老朋友喜相逢 《走出软件作坊》也喜相逢-SD2.0大会第一天
  2. Solidworks进阶之路
  3. Ubuntu20.04 安装HPC_SDK加速库
  4. Ceph MDS问题分析
  5. 微信小程序毕业设计选题和毕业论文怎么写,答辩流程是怎样的?
  6. c语言程序设计山东联盟第三章答案,C语言程序设计(山东联盟)知到章节测试答案...
  7. 正确的使用dd进行磁盘读写速度测试
  8. 麒麟高级服务器版V10 SP1 yum 源 龙芯 loongarch64
  9. 带头结点单链表逆置的四种方法思路和实现
  10. php对接花呗,对接 花呗分期 不支持问题