C++11模板元编程-std::enable_if示例详解

C++11中引入了std::enable_if函数,函数原型如下:

template< bool B, class T = void >
struct enable_if;

可能的函数实现:

template<bool B, class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> { typedef T type; };

由上可知,只有当第一个模板参数为true时,enable_if会包含一个type=T的公有成员,否则没有该公有成员。

头文件:

#include <type_traits>

std::enable_if使用场景

1、限制模板函数的参数类型

在某些场景下,我们需要实现只有特定类型可以调用的模板函数。如下代码所示,通过对返回值使用std::enable_if和在模板参数中使用std::enable_if均实现了只允许整形参数调用函数的功能。

// enable_if example: two ways of using enable_if
#include <iostream>
#include <type_traits>

// 1. the return type (bool) is only valid if T is an integral type:
template <class T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
 is_odd (T i) {return bool(i%2);}

// 2. the second template argument is only valid if T is an integral type:
template < class T,
      class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}

int main() {

 short int i = 1;  // code does not compile if type of i is not integral

 std::cout << std::boolalpha;
 std::cout << "i is odd: " << is_odd(i) << std::endl;
 std::cout << "i is even: " << is_even(i) << std::endl;

 return 0;
}

当使用float类型参数调用函数时,程序会报错:

error: no matching function for call to 'is_odd(float&)'

2. 模板类型偏特化

在使用模板编程时,可以利用std::enable_if的特性根据模板参数的不同特性进行不同的类型选择。

如下所示,我们可以实现一个检测变量是否为智能指针的实现:

#include <iostream>
#include <type_traits>
#include <memory>

template <typename T>
struct is_smart_pointer_helper : public std::false_type {};

template <typename T>
struct is_smart_pointer_helper<std::shared_ptr<T> > : public std::true_type {};

template <typename T>
struct is_smart_pointer_helper<std::unique_ptr<T> > : public std::true_type {};

template <typename T>
struct is_smart_pointer_helper<std::weak_ptr<T> > : public std::true_type {};

template <typename T>
struct is_smart_pointer : public is_smart_pointer_helper<typename std::remove_cv<T>::type> {};

template <typename T>
typename std::enable_if<is_smart_pointer<T>::value,void>::type check_smart_pointer(const T& t)
{
  std::cout << "is smart pointer" << std::endl;
}

template <typename T>
typename std::enable_if<!is_smart_pointer<T>::value,void>::type check_smart_pointer(const T& t)
{
  std::cout << "not smart pointer" << std::endl;
}

int main()
{
  int* p(new int(2));
  std::shared_ptr<int> pp(new int(2));
  std::unique_ptr<int> upp(new int(4));

  check_smart_pointer(p);
  check_smart_pointer(pp);
  check_smart_pointer(upp);

  return 0;
}

程序输出:

not smart pointer
is smart pointer
is smart pointer

参考材料

http://www.cplusplus.com/reference/type_traits/enable_if/

https://en.cppreference.com/w/cpp/types/enable_if

总结

到此这篇关于C++11模板元编程-std::enable_if的文章就介绍到这了,更多相关C++11模板元编程-std::enable_if内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈C++模板元编程

    所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得异常灵活,能实现很多高级动态语言才有的特性(语法上可能比较丑陋,一些历史原因见下文).模板元编程的根在模板.模板的使命很简单:为自动代码生成提供方便.提高程序员生产率的一个非常有效的方法就是"代码复用",而面向对象很重要的一个贡献就是通过内部紧耦合和外部松耦合将"思想"转化成一个一个容易复用的"概念".但是面向对象提供的工具箱里面所

  • C++11模板元编程-std::enable_if示例详解

    C++11中引入了std::enable_if函数,函数原型如下: template< bool B, class T = void > struct enable_if; 可能的函数实现: template<bool B, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; 由上可知,只有当第一个模板参数为

  • Kotlin编程基础数据类型示例详解

    目录 本文总览 1.数值类型 2.布尔型 3.字符串 3.1 字符串字面值 3.2 字符串模板 4.数组 4.1 普通数组 4.2 原⽣类型数组 5.类型检测和类型转换 5.1 智能转换 5.2 is 与 !is 操作符 5.3 转换操作符: as 与 as? 总结 本文总览 上一篇学习了Kotlin基础语法知识,本篇开始会深入探讨一下Kotlin各个基础语法点.首先来熟悉Kotlin的数据类型和类型转换版块. 1.数值类型 在Kotlin中提供了数值类型: 整数类型:Byte,Short,In

  • 适合面向ChatGPT编程的架构示例详解

    目录 新的需求 领域知识 架构设计 管道架构 分层架构 类分层神经网络的架构 总结一下 新的需求 我们前面爬虫的需求呢,有些平台说因为引起争议,所以不让发,好吧,那我们换个需求,本来那个例子也不好扩展了.最近AI画图也是比较火的,那么我们来试试做个程序帮我们生成AI画图的prompt. 首先讲一下AI话题的prompt的关键要素,大部分的AI画图都是有一个个由逗号分割的关键字,也叫subject,类似下面这样: a cute cat, smile, running, look_at_viewer

  • Python面向对象编程repr方法示例详解

    目录 为什么要讲 __repr__ 重写 __repr__ 方法 str() 和 repr() 的区别 为什么要讲 __repr__ 在 Python 中,直接 print 一个实例对象,默认是输出这个对象由哪个类创建的对象,以及在内存中的地址(十六进制表示) 假设在开发调试过程中,希望使用 print 实例对象时,输出自定义内容,就可以用 __repr__ 方法了 或者通过 repr() 调用对象也会返回 __repr__ 方法返回的值 是不是似曾相识....没错..和 __str__ 一样的

  • Kotlin编程条件控制示例详解

    目录 本文总览 1. When 表达式 2. If 表达式 总结 本文总览 本篇来看看 Kotlin的条件控制,这一节知识点 建议与Java中的条件结构类比,会很好理解并记住. 1. When 表达式 在 Kotlin 用 when 来定义多个分支的条件表达式.Kotlin中这个语法与 java 中的 switch 语句非常类似.代码块的执行就是将参数与所有的分⽀条件顺序⽐较,直到满⾜某个分⽀条件:(示例 ) when (x) { 1 -> print("x == 1") 2 -

  • go语言编程实现递归函数示例详解

    目录 前言 函数中的 return 递归的问题 总结 前言 本篇文章主要是记录一下在 GScript 中实现递归调用时所遇到的坑,类似的问题在中文互联网上我几乎没有找到相关的内容,所以还是很有必要记录一下. 在开始之前还是简单介绍下本次更新的 GScript v0.0.9 所包含的内容: 支持可变参数 优化 append 函数语义 优化编译错误信息 最后一个就是支持递归调用 先看第一个可变参数: //formats according to a format specifier and writ

  • java异步编程CompletableFuture使用示例详解

    目录 一.简单介绍 二.常见操作 1.使用默认线程池 2.使用自定义线程池 3.获取线程的执行结果 三.处理异步结算的结果 四.异常处理 五.组合 CompletableFuture 六.并行运行多个 CompletableFuture 七.案例 1.从多个平台获取书价格 2.从任意一个平台获取结果就返回 一.简单介绍 CompletableFuture 同时实现了 Future 和 CompletionStage 接口. public class CompletableFuture<T> i

  • iOS中的类、元类以及isa示例详解

    前言 对于类相信大家都知道是什么,如果看过runtime的源码或者看过相关的文章对isa肯定也不陌生,不过元类(meta class)大家可能就比较陌生了.不过大家也不要担心,我会细细道来,让大家明白它到底是个什么东西. 先看一段大家非常熟悉的代码: Person *person = [[Person alloc] init]; 为什么Person类名就能调用到alloc方法吗?到底怎么找到了alloc的方法了呢? 1.首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应实现

  • django模板语法学习之include示例详解

    前言 在很多网站中,基本上的都会有一个开头和一个结尾,在每一个网页中都会显示.相对于这种的来说,在Django中,最好的方法就是使用include的标签,在每一个模板中都加入这个开头和结尾的标签. include标签使用 假如我们有以下模板index.html,代码为: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>

  • python多线程编程方式分析示例详解

    在Python多线程中如何创建一个线程对象如果你要创建一个线程对象,很简单,只要你的类继承threading.Thread,然后在__init__里首先调用threading.Thread的__init__方法即可 复制代码 代码如下: import threading  class mythread(threading.Thread):  def __init__(self, threadname):  threading.Thread.__init__(self, name = thread

随机推荐