欢迎光临
我们一直在努力

深入理解C++ 可变参数模板

可变参数模板(Variadic Templates)介绍

可变参数模板是 C++11 引入的一项重要特性,它允许模板定义接受任意数量的模板参数(包括零个)。这让函数模板和类模板能够处理数量不定的参数列表,极大地增强了泛型编程的灵活性和表达能力。

核心概念

参数包(Parameter Pack):使用 typename… Args 或 class… Args 声明的模板参数,称为模板参数包;函数参数中也可以使用 Args… args 这样的函数参数包。

展开参数包:要使用包中的各个参数,必须展开它。常见的展开方式包括:递归展开:通过递归调用函数模板,每次剥离一个参数,直到包为空。

折叠表达式(C++17):使用二元运算符对包中的所有参数进行折叠计算,语法为 ( … op pack ) 或 ( pack op … ) 等。

初始化列表展开:利用 std::initializer_list 或数组构造来一次性展开。

典型应用场景

实现通用的打印函数(如 print),接受任意类型和数量的参数。

实现类型安全的变参函数(替代 C 风格的 va_list)。

用于元编程、委托构造、完美转发等高级场景。

示例1:递归展开(兼容 C++11/14)

#include <iostream>

// 终止函数:当参数包为空时调用
void print() {
std::cout << std::endl;
}

// 递归函数:每次处理第一个参数,然后递归处理剩余参数
template<typename T, typename… Args>
void print(T first, Args… rest) {
std::cout << first << " "; // 打印当前参数
print(rest…); // 递归展开剩余参数包
}

int main() {
print(1, 2.5, "hello", 'c');
// 输出:1 2.5 hello c
return 0;
}

示例2:折叠表达式(C++17 起,更简洁)

#include <iostream>

// 使用一元右折叠 (args op …) 对所有参数进行求和
template<typename… Args>
auto sum(Args… args) {
return (args + …); // 展开为 args1 + (args2 + (args3 + …))
}

// 使用逗号表达式折叠,实现打印所有参数
template<typename… Args>
void printAll(Args… args) {
(std::cout << … << args) << std::endl; // 左折叠,连续输出
}

int main() {
std::cout << "Sum: " << sum(1, 2, 3, 4) << std::endl; // 输出 10
printAll(1, 2.5, "hello", 'c'); // 输出 12.5helloc (无空格)
// 若想要带空格,可以稍作修改:(std::cout << … << (args, " ")) 但需注意类型
return 0;
}

赞(0)
未经允许不得转载:171主机测评 » 深入理解C++ 可变参数模板
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址