题目
编写程序,演示现代 C++11 引入的“可变参数模板”(Variadic Templates)与参数包(Parameter Pack Args...)。不借助任何 C 语言 va_list 的类型隐患宏,通过模板函数递归解包展开(Recursive Unpacking)以及 C++17 引入的折叠表达式(Fold Expression (... , expr)),构建绝对类型安全、支持无限个任意异构类型参数的格式化流式打印器 safePrint。
输入格式:无需外部输入。
输出格式:输出递归参数包展开与折叠表达式打印混合异构类型的日志。
数据范围与约定:参数包展开、sizeof... 操作符、C++17 折叠表达式。
思路与算法
1. 解决 C 语言 printf 的致命缺陷
C 语言的 printf("%d", str) 会发生致命内存访问越界,且无法打印自定义对象。C++ 可变参数模板在编译期精准展开每个参数的具体类型,兼具绝对类型安全与极致性能。
2. 递归展开的两件套
①递归基终止函数(Base Case):处理 0 个或 1 个参数;②递归展开函数:剥离首个参数 const T& first,对剩余参数包 const Rest&... rest 进行尾递归调用展开。
3. C++17 折叠表达式极致简化
C++17 支持一元/二元折叠:(std::cout << ... << args) << '\n';,一行代码即可彻底消灭繁琐的递归基终止函数!
完整程序
#include <iostream>
#include <string>
// --- 方法 1:C++11 经典递归解包展开 ---
// 1. 递归基终止函数:无参数时收尾换行
void printPackC11() {
std::cout << "\n";
}
// 2. 递归解包函数:剥离第一个参数,剩余包尾递归
template <typename T, typename... Rest>
void printPackC11(const T& first, const Rest&... rest) {
std::cout << "[" << first << "] ";
printPackC11(rest...); // 递归展开参数包
}
// --- 方法 2:C++17 逗号折叠表达式 (Fold Expression) ---
template <typename... Args>
void printPackC17(const Args&... args) {
std::cout << "参数包元素总个数 sizeof...(args): " << sizeof...(args) << "\n";
// C++17 逗号折叠展开
((std::cout << "{" << args << "} "), ...);
std::cout << "\n";
}
int main() {
std::cout << "--- 1. C++11 递归模板解包 ---\n";
printPackC11(2026, 3.14, "Modern C++", 'A', true);
std::cout << "\n--- 2. C++17 折叠表达式解包 ---\n";
printPackC17("Thread-Pool", 8, "Workers", 99.98);
return 0;
}运行示例
输出:
--- 1. C++11 递归模板解包 ---
[2026] [3.14] [Modern C++] [A] [1]
--- 2. C++17 折叠表达式解包 ---
参数包元素总个数 sizeof...(args): 4
{Thread-Pool} {8} {Workers} {99.98}