C++可变参数模板类通过递归和特化方式展开

2024-05-10 10:28

本文主要是介绍C++可变参数模板类通过递归和特化方式展开,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

可变参数模版类有2种方式展开参数包:通过继承和通过递归+特化。在此只举例一个后着的例子以阐述展开的方式和过程。这些内容其实书上都有,我只是在看《深入C++11 代码优化与工程应用》一书中遇到了些困惑,可能书中的写法与我的理解不对版,在此记录一下从误解到了知的经过。

书中提到了通过模板元编程方式检查某个类型是否在一个类型列表里面,比如:

cout << Contains<int, char, int>::value << endl;
cout << Contains<int, char, float>::value << endl;
cout << Contains<int, char>::value << endl;
cout << Contains<int>::value << endl;

第一个模板实参int是要检查的类型,检查它是否存在于后面的列表中(通过可变参数)。只有第一个value是true,后面三个例子都是false。下面是实现代码:

template<typename T, typename... Rest>
struct Contains: std::true_type {};template <typename T, typename Head, typename... Rest> //partial specialization
struct Contains<T, Head, Rest...>
: std::conditional<std::is_same<T, Head>::value, std::true_type, Contains<T, Rest...> >::type {};template<typename T> //partial specialization
struct Contains<T>: std::false_type {};

除了第一行的template外,只要类名后面还带有有尖括号的叫做模板特化,也就是说这段code第一个模板是Contains普通模板,后面两个是Contains特化模板。对普通模板类、全特化类、偏特化类的匹配优先级从高到低进行排序是:

全特化类 > 偏特化类 > 主版本模板类

于是乎,当语句Contains<int, char, int>::value想要实例化时尽量先找特化版本,无特化可选才匹配普通版本,下面是借助C++ Insights工具展现模板展开的中间过程:

可以看到普通版本压根没有起作用,原书中普通模板的写法其实误导了我,以为Contains<int, char, int>匹配特化版而Contains<int, int>匹配普通版,其实不是的。这里只是给了个普通版本的实现,继承了std::true_type而已。

template<typename T, typename... Rest>
struct Contains: std::true_type {};

我如果想要将普通版仅有个声明,在我们当前需求下,经试验也是可以的:

template<typename T, typename... Rest>
struct Contains;

因为Contains<int, int>看似能同时满足特化版和普通版,它优先选择特化版,符合匹配优先级规律。

这篇关于C++可变参数模板类通过递归和特化方式展开的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976179

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

Vue3视频播放组件 vue3-video-play使用方式

《Vue3视频播放组件vue3-video-play使用方式》vue3-video-play是Vue3的视频播放组件,基于原生video标签开发,支持MP4和HLS流,提供全局/局部引入方式,可监听... 目录一、安装二、全局引入三、局部引入四、基本使用五、事件监听六、播放 HLS 流七、更多功能总结在 v

使用Java填充Word模板的操作指南

《使用Java填充Word模板的操作指南》本文介绍了Java填充Word模板的实现方法,包括文本、列表和复选框的填充,首先通过Word域功能设置模板变量,然后使用poi-tl、aspose-words... 目录前言一、设置word模板普通字段列表字段复选框二、代码1. 引入POM2. 模板放入项目3.代码

Java发送SNMP至交换机获取交换机状态实现方式

《Java发送SNMP至交换机获取交换机状态实现方式》文章介绍使用SNMP4J库(2.7.0)通过RCF1213-MIB协议获取交换机单/多路状态,需开启SNMP支持,重点对比SNMPv1、v2c、v... 目录交换机协议SNMP库获取交换机单路状态获取交换机多路状态总结交换机协议这里使用的交换机协议为常

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型