std::enable_if 的几种用法
https://yixinglu.gitlab.io/enable_if.html
std::enable_if 的几种用法
tech 12cpp 2
std::enable_if 顾名思义,满足条件时类型有效。作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中。它的定义也异常的简单:
template <bool, typename T=void>
struct enable_if {
};
template
struct enable_if<true, T> {
using type = T;
};
由上可知,只有当第一个模板参数为 true 时,type 才有定义,否则使用 type 会产生编译错误,并且默认模板参数可以让你不必指定类型。下面说说它的几种使用方法:
用法一:类型偏特化
在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。例如:
template <typename T, typename Enable=void>
struct check;
template
struct check<T, typename std::enable_if<T::value>::type> {
static constexpr bool value = T::value;
};
上述的 check 只希望选择 value==true 的 T,否则就报编译时错误。如果想给用户更友好的提示,可以提供结构体的原型定义,并在其中进行 static_assert 的静态检查,给出更明确的字符串说明。
用法二:控制函数返回类型
对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看 tuple 的获取第 k 个元素的 get 函数:
template <std::size_t k, class T, class… Ts>
typename std::enable_if<k==0, typename element_type_holder<0, T, Ts…>::type&>::type
get(tuple<T, Ts…> &t) {
return t.tail;
}
template <std::size_t k, class T, class… Ts>
typename std::enable_if<k!=0, typename element_type_holder<k, T, Ts…>::type&>::type
get(tuple<T, Ts…> &t) {
tuple<Ts…> &base = t;
return get(base);
}
由于函数模板不能偏特化,通过 enable_if 便可以根据 k 值的不同情况选择调用哪个 get,进而实现函数模板的多态。
用法三:校验函数模板参数类型
有时定义的模板函数,只希望特定的类型可以调用,参考 cppreference 官网示例,很好的说明了如何限制只有整型可以调用的函数定义:
template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
is_odd(T t) {return bool(t%2);
}template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even(T t) {return !is_odd(t);
}
一个通过返回值,一个通过默认模板参数,都可以实现校验模板参数是整型的功能。
std::enable_if 的几种用法相关推荐
- SNIFE 和 std::enable_if
类型基础 在回顾模板之前,需要明确一个概念:模板编程是针对类型的计算..这和我们平时的代码不同,我们平时写的程序都是针对数据的. 在模板元编程中,typename 用于定义类型:using 用于给模板 ...
- std::enable_if的用法
一.测试程序1 #include <iostream> #include <type_traits> using namespace std; template <typ ...
- std::enable_if
std::enable_if 顾名思义,满足条件时类型有效.作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中.它的定义也异常的简单: template ...
- c++11 std::enable_if在模板偏特化的妙用
1.模板自动推导功能. 先看个例子: 在调用TestTemplate函数时, 我们可以在函数后面加上<类型>无歧义地指定调用的版本. 结果如下: 由于模板参数在函数参数中的位置是固定的,编 ...
- static的三种用法,定义静态变量,静态函数,静态代码块!
static的三种用法,定义静态变量,静态函数,静态代码块! 1.定义静态变量 class PersonStatic { //静态变量的特点 //1.静态变量无需生成对象就可被调用,可以使用类名和对象 ...
- 【C++】41. std::copy和assign的用法
对于std::copy的用法,可以参考 https://blog.csdn.net/a_ran/article/details/17385911,我这里直接介绍对于std::vector来说std:: ...
- c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast...
C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...
- C++ 命名空间三种用法
C++ 命名空间三种用法 1.#include <iostream> using namespace std; //直接using会把整个空间里的东西全部引入,这样做的优点是省事,缺点是如 ...
- c++中using的几种用法
最近在使用中,发现了一种以前没学过的using用法,于是在这里,将using的几种用法总结一下. 先来说说我新学会的一种用法,就是起别名,我们都知道typedef可以给我们起别名,using也可以,用 ...
最新文章
- 清华AI学堂班:姚期智担任首席教授,2019年首批招收30人
- eclipse自定义快捷键
- 云炬Android开发笔记 14 个人中心、图片裁剪、图片上传、收货地址、消息推送、权限管理等功能开发与一键式封装
- OpenCV camshift算法的实例(附完整代码)
- Redis中的可用性保证之Sentinel 原理
- PL/SQL之高级篇
- 那些有趣的电子漫画合集
- Leetcode--442. 数组中重复的数据
- gevent版TCP服务器
- 薪资不如 Java、C,BAT 需求大,揭秘 Python 程序员跳槽现状!
- spring4.0.0的配置和使用
- 一篇文章学懂ADB命令和Monkey命令
- python怎么算二元一次方程_利用Python求解二元一次方程
- 【Android测试】在AndroidStudio中进行单元测试
- html用css设置图片大小,css如何设置图片大小?
- 财会法规与职业道德【9】
- 【设计模式 三】实战工厂汽车代工之工厂模式-简单模式
- SharedPreferences in credential encrypted storage are not available until after user is unlocked
- GBase 8c产品高级特性介绍
- Go语言如何高效的进行字符串拼接(6种方式进行对比分析)