C++可变参数模板通过参数包与递归展开/折叠表达式支持任意数量和类型的模板参数,用于实现类型安全的泛型工具;需用typename...定义类型包、Args&&...定义值包,并在合法上下文中以args...形式展开。
C++ 可变参数模板(Variadic Templates) 的核心是支持任意数量、任意类型的模板参数,常用于实现类型安全的泛型工具,比如 std::make_tuple、std::print(C++23)、日志函数、工厂模式等。它不是简单“传参”,而是通过**参数包(parameter pack)+ 递归展开/折叠表达式**来实现逻辑。
声明可变模板时用 typename... 或 class... 定义类型参数包,用 Args&&... 定义值参数包:
template struct Tuple {}; —— 类型包,可为空template void func(Args&&... args) { ... } —— 值包,支持完美转发展开必须在支持“包展开”的上下文中进行,例如函数调用、初始化列表、sizeof
...、折叠表达式等。直接写 args 是非法的,必须写成 args...(尾随省略号表示展开)。
当需要逐个处理参数(如打印、构造对象),常用“头-尾”递归分解:
head)和剩余参数包(tail...)head,再递归调用自身处理 tail...
示例:类型安全的多参数打印函数
#includetemplate void print(T&& t) { std::cout << t << '\n'; } template void print(T&& t, Args&&... args) { std::cout << t << ' '; print(std::forward(args)...); // 展开 tail 并递归 } // 使用:print(1, "hello", 3.14, std::string("world"));
避免手动递归,用 (expr op ...) 或 (... op expr) 一行展开并计算。适用于逻辑可结合(如 +、&&、, )的场景:
(std::cout —— 左折叠,等价于 ((std::cout return (... && (std::is_integral_v)); —— 检查所有参数是否为整型auto sum = (0 + ... + args); —— 计算数值参数和(要求所有 args 支持 +)可变参数模板类常配合别名模板、递归继承或成员模板特化来构建异构容器:
std::tuple 存储参数包,其内部就是靠递归基类或联合体+索引元组实现std::tuple data;
std::make_tuple(std::forward(args)...) 转发初始化std::get(data) 或结构化绑定(C++17)关键点:类模板本身不“执行”逻辑,而是把参数包保存下来,留待后续编译期推导或运行时索引操作。