c++中的可变参数模板(variadic templates)怎么用_c++模板编程黑魔法【C++11】
技术百科
冰火之心
发布时间:2026-01-01
浏览: 次 可变参数模板是C++11核心特性,支持任意数量和类型的模板参数,依赖类型参数包(class.../typename...)和函数参数包(Args... args),通过递归展开或折叠表达式(如f(args...)、(args, ...))实现类型安全的泛型编程。
可变参数模板是 C++11 引入的核心特性之一,它让模板能接受任意数量、任意类型的参数,是实现类型安全的泛型容器、完美转发、日志函数、元编程等高级功能的基础。用得好,代码简洁又高效;用得不熟,容易陷入递归展开和参数包(parameter pack)的迷雾中。
基础写法:声明与展开参数包
可变参数模板的关键在于 参数包(template parameter pack) 和 函数参数包(function parameter pack),以及它们的展开方式。
- 声明模板时用
class...或typename...表示类型参数包,如template - 函数参数列表中用
Args... args表示值参数包 - 展开必须在支持“逗号表达式上下文”的地方进行,比如函数调用、初始化列表、基类列表等
- 最常用展开方式:
f(args...)(调用时展开)、{f(args)...}(C++17 折叠表达式)、int arr[] = {g(args)...}(初始化数组)
递归展开:处理参数包的经典模式
由于不能直接对参数包做循环,传统做法是靠“头尾分离”+递归终止来逐个处理。典型结构:
- 先写一个只接受一个参数的重载(递归终点),例如
void print(T t) { std::cout - 再写一个可变参数版本,取出第一个参数(
first),其余递归调用自身:templatevoid print(T first, Rest... rest) { std::cout - 注意:递归调用
print(rest...)会自动推导剩余参数类型,直到
只剩一个参数触发终点重载
折叠表达式(C++17):一行搞定多数聚合操作
告别繁琐递归!C++17 引入折叠表达式,语法简洁且高效:
- 一元右折叠:
(args && ...)等价于args1 && args2 && args3 && ... - 一元左折叠:
(... && args)同样效果,但结合律不同(对&&/||无影响) - 二元折叠:
(init + ... + args)展开为init + arg1 + arg2 + ... - 实用例子:安全打印所有参数
((std::cout —— 利用逗号表达式顺序求值
完美转发与参数包转发:保持值类别不变
配合 std::forward 和万能引用(T&&),可变参数模板能真正实现“原样转发”:
- 写法:
templatevoid wrapper(Args&&... args) { func(std::forward(args)...); } - 关键点:
Args&&是万能引用,std::forward(args)恢复原始值类别(lvalue/rvalue) - 这是
std::make_unique、std::thread构造等标准库功能的底层支撑
基本上就这些。可变参数模板不是炫技工具,而是构建现代 C++ 基础设施的砖块——理解参数包、掌握展开时机、善用折叠与转发,就能把黑魔法变成日常生产力。
# 这是
# 能把
# 第一个
# 关键在于
# 最常用
# 循环
# 递归
# c++
# int
# void
# class
# 泛型
# function
# 时用
# print
# 值参数
# 只剩
# 可变参数
# 用得
# 不熟
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭系统声音_Win11系统提示音静
- 如何提升Golang JSON序列化性能_Gola
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Win11怎样安装企业微信_Win11安装企业微信
- 如何使用正则表达式批量替换重复的星号-短横模式为固
- Win11怎么关闭内容自适应亮度_Windows1
- PowerShell怎么创建复杂的XML结构
- 如何使用 Selenium 正确获取篮球参考网站球
- Win11怎么清理C盘下载文件夹_Win11清理下
- mac怎么打开终端_MAC终端Terminal使用
- 如何在 Windows 11 中使用 AlomWa
- 如何在 Go 后端安全获取并验证前端存储的 JWT
- C#如何使用XPathNavigator高效查询X
- 静态属性修改会影响所有实例吗_php作用域操作符下
- Mac如何与安卓手机传文件_Mac和Android
- php8.4xdebug无法调试怎么办_php8.
- Python如何创建带属性的XML节点
- 如何在Golang中解压文件_Golang com
- c++如何获取map中所有的键_C++遍历键值对提
- Win11怎么打开注册表_Windows 11注册
- 如何在 IIS 上为 ASP.NET 6 应用排除
- Windows 11如何查看系统激活密钥_Wind
- 如何处理“XML格式不正确”错误 常见XML we
- Win11怎么设置组合键快捷方式_Windows1
- Win10路由器怎么隐藏ssid Win10隐藏w
- Win11无法拖拽文件到任务栏怎么办_Win11开
- php嵌入式日志记录怎么实现_php将硬件数据写入
- 如何在 Go 中高效缓存与分发网络视频流
- GML (Geography Markup Lan
- 如何在Windows中创建新的用户账户?(标准与管
- Win11如何更改任务栏颜色 Win11自定义任务
- 用lighttpd能运行php吗_lighttpd
- c++怎么调用nana库开发GUI_c++ 现代风
- Win11怎么开启上帝模式_创建Windows 1
- c++怎么使用std::filesystem遍历文
- 如何使用Golang实现错误包装与传递_Golan
- 短链接怎么用php递归还原_多层加密链接的处理法【
- c++中的Tag Dispatching是什么_c
- Python函数接口文档化_自动化说明【指导】
- 一文详解网站被黑客入侵挂马解决办法
- VSC怎样用终端运行PHP_命令行执行脚本的步骤【
- Python包结构设计_大型项目组织解析【指导】
- php485函数怎么捕获异常_php485错误处理
- Win10怎样安装Word样式库_Win10安装W
- Windows怎样关闭开始菜单推荐广告_Windo
- c++怎么使用std::unique实现去重_c+
- 如何在 Laravel 中通过嵌套关联关系进行 o
- Windows10电脑怎么连接蓝牙设备_Win10
- php控制舵机角度怎么调_php发送pwm信号控制
- 如何在 Go 中正确反序列化 XML 多节点数组(

只剩一个参数触发终点重载
QQ客服