C++模板元编程(一)——可变参数模板

news2024/10/6 12:25:52

这个系列主要记录C++模板元编程的常用语法


文章目录

  • 引言
  • 语法
  • 应用
    • 函数模板
      • 可变参数的打印
      • 可变参数的最小/最大函数
    • 类模板
  • 参考文献


引言

在C++11之前,函数模板和类模板只支持含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含任意个(包括0个)模板参数,即可变参数模板。


语法

template<typename... Types>

其中 ... 可接纳的模板参数>=0
如果不希望产生模板参数个数为0的变长参数模板,则可以采用以下定义:

template<typename Head, typename... Tail>

由于多了Head类型,该模板必须有一个及以上的模板参数。


应用

函数模板

可变参数的打印

函数模板中一种常见的使用可变参数模板的场景是以递归的方式取出可用参数:

#include <iostream>

void print() {}

template<typename T, typename... Types>
void print(const T& firstArg, const Types&... args) {
	std::cout << firstArg << " " << sizeof...(args) << std::endl;
	print(args...);
}

template <typename... Types>
void print(const Types&... args) {
	std::cout << "print(...)" << std::endl;
}

int main(int argc, char* argv[]) {
	print(3.0f, "hello world", 10);
	return 0;
}

上面例子表示我们想要输出一个单精度浮点值+字符串+整型值:

  • 上面的 void print() {} 代表模板递归的终止。
  • print(args...) 展开参数,向下模板递归。
  • sizeof...(args) 得到参数的个数。

最终输出为

考虑如下情况,如果除了有上面的模板,我们还定义了一个完全泛化的模板:

template <typename... Types>
void print(const Types&... args) {
  std::cout << "print(...)" << std::endl;
}

那么输出结果是怎么样的?
答案是还是输出上面的值,这是因为编译器对于偏泛化和偏特化都满足的情况,会选择偏特化的模板。


可变参数的最小/最大函数

有时我们想得到可变参数的最小/最大函数,可以如下实现:

#include <iostream>

template <typename T>
T m_min(T value) {
  return value;
}

template <typename T, typename... Types>
T m_min(T value, Types... args) {
  return std::min(value, m_min(args...));
}

int main(int argc, char *argv[]) {
  std::cout << my_min(4, 3, 1, 2) << std::endl;

	return 0;
}


类模板

可变参数模板也可以用于类模板中,比如STL中的tuple

#include <iostream>

template<typename... Values> class tuple;
template<> class tuple<> {};

template<typename Head, typename... Tail>
class tuple<Head, Tail...>
	: private tuple<Tail...>
{
	typedef tuple<Tail...> inherited;
public:
	tuple() {}
	tuple(Head v, Tail... vtail) : m_head(v), inherited(vtail...) {}
	Head& head() { return m_head; }
	inherited& tail() { return *this; }
protected:
	Head m_head;
};

int main(int argc, char* argv[]) {
	tuple<float, std::string, int> t(3.0f, "hello world", 10);
	std::cout << t.head() << " " << t.tail().head() << " " << t.tail().tail().head() << std::endl;
	return 0;
}

通过可变参数模板,实现递归继承,根基类为 template<> class<>{},父类成员在内存中位于子类成员之前。

这里的输出为


参考文献

【C++】C++11可变参数模板(函数模板、类模板)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1903450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytorch 实践手写数字识别深度学习网络 LeNet-5

Pytorch 实践手写数字识别深度学习网络 LeNet-5 文章目录 Pytorch 实践手写数字识别深度学习网络 LeNet-5认识 LeNet-5认识数据集处理数据集下载数据集读取数据定义Dataset的继承类把数据进行载入载入dataloader 编写网络编写训练与测试代码实践结果展示完整代码 训练手写体识别…

什么是反射?

什么是反射&#xff1f; 1、反射的基本概念2、 获取Class对象3、获取类的成员变量、方法和构造方法3.1 获取成员变量3.2 获取方法3.3 获取构造方法3.4 动态调用方法 4、反射的优缺点 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 反射&…

Unity3D 转换微信小游戏指引 02

Unity3D 转换微信小游戏指引系列&#xff08;第二期&#xff09; 云开发 当小游戏打包后的首包占用内存比较大&#xff08;大约是 14M 左右&#xff09;&#xff0c;首包资源加载方式就不能选择小游戏包内了。 这时就需要购买服务器&#xff0c;把首包放到服务器上&#xff…

Drools开源业务规则引擎(二)- Drools规则语言(DRL)

文章目录 1.DRL文件的组成&#xff1a;2.package3.import4.function5.query6.declare7.global8.rule8.1.规则属性8.2.LHS8.2.1.语法格式8.2.2.运算符优先级8.2.3.特殊的运算符1.matches, not matches2.contains, not contains3.memberOf, not memberOf4.in, notin5.soundslike6…

尚品汇-(十三)

&#xff08;1&#xff09;查询sku列表 在ManageService 中添加 /*** SKU分页列表* param pageParam* return*/ IPage<SkuInfo> getPage(Page<SkuInfo> pageParam);接口实现类 Override public IPage<SkuInfo> getPage(Page<SkuInfo> pageParam) {Qu…

STM32-01 推挽输出-点亮LED

本文以STM32中点亮LED为例&#xff0c;解读推挽输出的原理 推挽输出介绍 所谓的推挽输出&#xff0c;就是通过控制输出控制模块&#xff0c;打开或者关闭P-MOS或者N-MOS。 ─ 推挽模式下&#xff1a;输出寄存器上的’0’激活N-MOS&#xff0c;而输出寄存器上的’1’将激活P-M…

IDEA与通义灵码的智能编程之旅

1 概述 本文主要介绍在IDEA中如何安装和使用通义灵码来助力软件编程,从而提高编程效率,创造更大的个人同企业价值。 2 安装通义灵码 2.1 打开IDEA插件市场 点击IDEA的设置按钮,下拉选择Plugins,如下: 2.2 搜索通义灵码 在搜索框中输入“通义灵码”,如下: 2.3 安…

74HC165芯片验证

目录 0x01 74HC165芯片介绍0x02 编程实现 0x01 74HC165芯片介绍 74HC165的引脚定义如下&#xff0c;长这个样子 ABCDEFGH是它的八个输入引脚&#xff0c;例如你可以将它连接按键&#xff0c;让它来读取8个按键值。也可以将他级联其它的74165&#xff0c;无需增加单片机GPIO引…

Apache Seata Mac下的Seata Demo环境搭建

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Mac下的Seata Demo环境搭建&#xff08;AT模式&#xff09; 前言 最近因为工作需要&#xf…

强化学习的数学原理:时序差分算法

概述 之前第五次课时学习的 蒙特卡洛 的方法是全课程当中第一次介绍的第一种 model-free 的方法&#xff0c;而本次课的 Temporal-Difference Learning 简称 TD learning &#xff08;时序差分算法&#xff09;就是第二种 model-free 的方法。而对于 蒙特卡洛方法其是一种 non…

DropNotch for Mac v1.0.1 在 Mac 刘海快速使用 AirDrop

应用介绍 DropNotch 是一款专为Mac设计的应用程序&#xff0c;可以将MacBook的凹口区域&#xff08;刘海&#xff09;转换为文件放置区。 功能特点 文件共享: 用户可以将文件拖放到MacBook的凹口区域&#xff0c;并通过AirDrop、邮件、消息等方式轻松共享。多显示器支持: 即…

【经验篇】Spring Data JPA开启批量更新时乐观锁失效问题

乐观锁机制 什么是乐观锁&#xff1f; 乐观锁的基本思想是&#xff0c;认为在大多数情况下&#xff0c;数据访问不会导致冲突。因此&#xff0c;乐观锁允许多个事务同时读取和修改相同的数据&#xff0c;而不进行显式的锁定。在提交事务之前&#xff0c;会检查是否有其他事务…

3.js - 裁剪场景(多个scence)

不给newScence添加background、environment时 给newScence添加background、environment时 源码 // ts-nocheck// 引入three.js import * as THREE from three// 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls// 导入lil.gui impor…

leetcode每日一题-3033. 修改矩阵

题目描述&#xff1a; 解题思路&#xff1a;简单题目&#xff0c;思路非常直接。对列进行遍历&#xff0c;记录下最大值&#xff0c;然后再遍历一遍&#xff0c;把-1替换为最大值。需要注意的是进行列遍历和行遍历是不同的。 官方题解&#xff1a; class Solution { public:v…

工控人最爱的PLC触摸屏一体机,有多香

PLC触摸屏一体机是什么 PLC触摸屏一体机&#xff0c;听起来可能有点技术化&#xff0c;但简单来说&#xff0c;它就是一个集成了可编程逻辑控制器&#xff08;PLC&#xff09;和触摸屏的智能设备。这种设备不仅能够执行自动化控制任务&#xff0c;还能实时显示和操作设备状态&a…

作业训练二编程题3. 数的距离差

【问题描述】 给定一组正整数&#xff0c;其中最大值和最小值分别为Max和Min, 其中一个数x到Max和Min的距离差定义为&#xff1a; abs(abs(x-Max)-(x-Min)) 其中abs()为求一个数的绝对值 【输入形式】 包括两行&#xff0c;第一行一个数n&#xff0c;表示第二行有n个正整数…

如何在PD虚拟机中开启系统的嵌套虚拟化功能?pd虚拟机怎么用 Parallels Desktop 19 for Mac

PD虚拟机是一款可以在Mac电脑中运行Windows系统的应用软件。使用 Parallels Desktop for Mac 体验 macOS 和 Windows 的最优性能&#xff0c;解锁强大性能和无缝交互。 在ParallelsDesktop&#xff08;PD虚拟机&#xff09;中如何开启系统的嵌套虚拟化功能&#xff1f;下面我们…

新手教学系列——前后端分离API优化版

在之前的文章《Vue 前后端分离开发:懒人必备的API SDK》中,我介绍了通过Object对象自动生成API的方法。然而,之前的代码存在一些冗余之处。今天,我将分享一个改进版本,帮助你更高效地管理API。 改进版API SDK 首先,让我们来看一下改进后的代码: import request from …

华为OD机试 - 来自异国的客人(Java 2024 D卷 100分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

自动控制:反馈控制

自动控制&#xff1a;反馈控制 反馈控制&#xff08;Feedback Control&#xff09;是一种在控制系统中通过测量输出信号&#xff0c;并将其与期望信号进行比较&#xff0c;产生误差信号&#xff0c;再根据误差信号调整输入来达到控制目标的方法。反馈控制是自动控制系统中最常…