(转载)std::enable_if 的几种用法 c++11
时间:2019-10-22
本文章向大家介绍(转载)std::enable_if 的几种用法 c++11,主要包括(转载)std::enable_if 的几种用法 c++11使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
今天看confluo源码中看到了std::enable_if这一个我不了解的语法,所以记录下来
转载地址:https://yixinglu.gitlab.io/enable_if.html
std::enable_if
顾名思义,满足条件时类型有效。作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中。它的定义也异常的简单:
1 template <bool, typename T=void> 2 struct enable_if { 3 }; 4 5 template <typename T> 6 struct enable_if<true, T> { 7 using type = T; 8 };
由上可知,只有当第一个模板参数为 true
时,type
才有定义,否则使用 type
会产生编译错误,并且默认模板参数可以让你不必指定类型。下面说说它的几种使用方法:
用法一:类型偏特化
在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。例如:
1 template <typename T, typename Enable=void> 2 struct check; 3 4 template <typename T> 5 struct check<T, typename std::enable_if<T::value>::type> { 6 static constexpr bool value = T::value; 7 };
上述的 check
只希望选择 value==true
的 T
,否则就报编译时错误。如果想给用户更友好的提示,可以提供结构体的原型定义,并在其中进行 static_assert
的静态检查,给出更明确的字符串说明
用法二:控制函数返回类型
对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看 tuple
的获取第 k 个元素的 get
函数:
1 template <std::size_t k, class T, class... Ts> 2 typename std::enable_if<k==0, typename element_type_holder<0, T, Ts...>::type&>::type 3 get(tuple<T, Ts...> &t) { 4 return t.tail; 5 } 6 7 template <std::size_t k, class T, class... Ts> 8 typename std::enable_if<k!=0, typename element_type_holder<k, T, Ts...>::type&>::type 9 get(tuple<T, Ts...> &t) { 10 tuple<Ts...> &base = t; 11 return get<k-1>(base); 12 }
由于函数模板不能偏特化,通过 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); }
一个通过返回值,一个通过默认模板参数,都可以实现校验模板参数是整型的功能。
原文地址:https://www.cnblogs.com/cutelife/p/11718614.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PAT (Basic Level) Practice (中文)1012 数字分类
- PAT (Basic Level) Practice (中文)1016 部分A+B
- PAT (Basic Level) Practice (中文)1086 就不告诉你
- PAT (Basic Level) Practice (中文)1061 判断题
- 使用IDEA写Python之pytest环境搭建及第一个程序编写
- PAT (Basic Level) Practice (中文)1026 程序运行时间
- PAT (Basic Level) Practice (中文)1091 N-自守数
- PAT (Basic Level) Practice (中文)1007 素数对猜想
- PAT (Basic Level) Practice (中文)1019 数字黑洞
- PAT (Basic Level) Practice (中文)1022 D进制的A+B
- 记一次线上商城系统高并发的优化
- 15个必须知道的JavaScript数组方法
- RedLock究竟是不是Redis分布式锁分布式环境下的银弹?
- PAT (Basic Level) Practice (中文)1023 组个最小数
- PAT (Basic Level) Practice (中文)1041 考试座位号