0

0

C++模板参数包扩展 折叠表达式应用

P粉602998670

P粉602998670

发布时间:2025-08-30 12:09:01

|

442人浏览过

|

来源于php中文网

原创

C++模板参数包扩展与折叠表达式支持可变参数的编译时处理,用于函数转发、编译计算、代码生成和类型推导,相比std::initializer_list更灵活高效,适用于异构类型和零运行时开销场景。

c++模板参数包扩展 折叠表达式应用

C++模板参数包扩展与折叠表达式,本质上是为了更灵活、更简洁地处理数量不定的模板参数。它们是现代C++元编程的基石,允许我们编写泛型代码,而无需预先知道参数的数量和类型。

参数包扩展与折叠表达式是C++11和C++17引入的特性,允许函数和类模板接受可变数量的参数。

解决方案

C++模板参数包扩展与折叠表达式主要应用于以下几个方面:

立即学习C++免费学习笔记(深入)”;

  1. 函数参数转发: 完美转发任意数量的参数到另一个函数。
  2. 编译时计算: 在编译时对参数包中的元素进行计算,例如求和、求最大值等。
  3. 代码生成: 根据参数包中的元素生成重复的代码片段,例如初始化列表、打印语句等。
  4. 类型推导: 根据参数包中的元素推导出复杂的类型,例如元组、变长数组等。

下面分别给出示例:

函数参数转发:

template
auto call_with_args(F&& f, Args&&... args) {
    return f(std::forward(args)...);
}

void print_args(int a, double b, std::string c) {
    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
}

int main() {
    call_with_args(print_args, 10, 3.14, "hello"); // 输出: a: 10, b: 3.14, c: hello
    return 0;
}

编译时计算 (折叠表达式):

template
auto sum(Args... args) {
    return (args + ...); // 右折叠,等价于 (arg1 + (arg2 + (arg3 + ...)))
}

int main() {
    std::cout << sum(1, 2, 3, 4, 5) << std::endl; // 输出: 15
    return 0;
}

代码生成 (结合初始化列表):

#include 
#include 

template
std::vector make_vector(Args&&... args) {
    return {std::forward(args)...};
}

int main() {
    std::vector v = make_vector(1, 2, 3, 4, 5);
    for (int x : v) {
        std::cout << x << " ";
    }
    std::cout << std::endl; // 输出: 1 2 3 4 5
    return 0;
}

类型推导 (元组):

蓝色商务公司网站(XDcms内核)1.0
蓝色商务公司网站(XDcms内核)1.0

本系统使用的是XDcms内核,在原来基础上做来相应修改 前台修改调用数据,可以使用{loop catid=栏目ID}{/loop}方式调用 主要功能: A、内容管理模型,自定义字段,更方便扩展功能。自带模型:单页模型、新闻模型、产品模型、招聘模型 B、栏目自定义,便于内容管理 C、内容模块化,二次开发更便捷。自带模块:幻灯片、QQ客服、友情链接、自定义表单(在线留言、简历管理) D、模板管理,后台

下载

虽然参数包本身不直接进行类型推导,但可以结合

std::tuple
等类型来间接实现:

#include 
#include 

template
auto make_tuple(Args&&... args) {
    return std::make_tuple(std::forward(args)...);
}

int main() {
    auto my_tuple = make_tuple(10, 3.14, "world");
    std::cout << std::get<0>(my_tuple) << std::endl; // 输出: 10
    std::cout << std::get<1>(my_tuple) << std::endl; // 输出: 3.14
    std::cout << std::get<2>(my_tuple) << std::endl; // 输出: world
    return 0;
}

如何理解C++模板参数包扩展的原理?

参数包扩展的核心在于将一个参数包“展开”成一个逗号分隔的列表。这个列表可以出现在函数参数列表、初始化列表、基类列表等多种上下文中。展开的过程是由编译器完成的,它会根据参数包中的元素数量和类型,生成相应的代码。

理解的关键点在于

...
运算符:

  • 在模板参数列表中,
    typename... Args
    表示声明一个名为
    Args
    的参数包。
  • 在函数参数列表中,
    Args&&... args
    表示声明一个名为
    Args
    的函数参数包,其中每个参数都是一个右值引用。
  • 在表达式中,
    f(args...)
    f(std::forward(args)...)
    表示将参数包
    Args
    展开,并将展开后的参数列表传递给函数
    f

折叠表达式有哪些不同的形式?

C++17引入了折叠表达式,它提供了一种更简洁的方式来处理参数包。折叠表达式有四种形式:

  • 右折叠 (unary right fold):
    (pack op ...)
    等价于
    (e1 op (e2 op (e3 op ... en)))
  • 左折叠 (unary left fold):
    (... op pack)
    等价于
    (((e1 op e2) op e3) op ... en)
  • 带初始值的右折叠 (binary right fold):
    (pack op ... op init)
    等价于
    (e1 op (e2 op (e3 op ... (en op init))))
  • 带初始值的左折叠 (binary left fold):
    (init op ... op pack)
    等价于
    (((((init op e1) op e2) op e3) op ... en)

其中,

pack
是参数包,
op
是运算符,
init
是初始值。 运算符可以是
+
,
-
,
*
,
/
,
&&
,
||
,
,
等等。

例如,求参数包中所有元素的乘积:

template
auto product(Args... args) {
    return (args * ... * 1); // 带初始值的右折叠,初始值为1
}

int main() {
    std::cout << product(1, 2, 3, 4, 5) << std::endl; // 输出: 120
    return 0;
}

参数包扩展与
std::initializer_list
有什么区别

虽然

std::initializer_list
也可以用来处理数量不定的参数,但它与参数包扩展有本质的区别:

  • std::initializer_list
    要求所有参数的类型相同,而参数包扩展允许参数具有不同的类型。
  • std::initializer_list
    在运行时构造一个数组,并将参数复制到该数组中,而参数包扩展在编译时展开,没有运行时的开销。
  • std::initializer_list
    只能用于初始化列表,而参数包扩展可以用于更广泛的场景,例如函数参数转发、编译时计算、代码生成等。

因此,参数包扩展比

std::initializer_list
更加灵活和强大,是现代C++中处理可变参数的首选方式。
std::initializer_list
主要用于构造函数初始化列表等特定场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1503

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

233

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

52

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

40

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

50

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

11

2026.01.31

漫画防走失登陆入口大全
漫画防走失登陆入口大全

2026最新漫画防走失登录入口合集,汇总多个稳定可用网址,助你畅享高清无广告漫画阅读体验。阅读专题下面的文章了解更多详细内容。

13

2026.01.31

php多线程怎么实现
php多线程怎么实现

PHP本身不支持原生多线程,但可通过扩展如pthreads、Swoole或结合多进程、协程等方式实现并发处理。阅读专题下面的文章了解更多详细内容。

1

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

c语言项目php解释器源码分析探索
c语言项目php解释器源码分析探索

共7课时 | 0.4万人学习

ThinkPHP6.x 微实战--十天技能课堂
ThinkPHP6.x 微实战--十天技能课堂

共26课时 | 1.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号