本文主要介绍如何展开可变参数的参数包
#include
#include
void printNumbers(int count, ...) {
// 声明va_list类型的变量
va_list args;
// 使用va_start将可变参数写入变量args
va_start(args, count);
for (int i = 0; i < count; i++) {
// 调用va_arg依次获取可变参数的参数值
int value = va_arg(args, int);
std::cout << value << " ";
}
// 使用va_end清理变量args
va_end(args);
std::cout << std::endl;
}
int main() {
printNumbers(3, 1, 2, 3); // 输出: 1 2 3
printNumbers(5, 1, 2, 3, 4, 5); // 输出: 1 2 3 4 5
}
使用va_list感觉还挺麻烦的,需要提前知道参数个数,并且还得需要知道入参类型。因此不如直接使用数组了。
#include
template
void printNumbers(std::initializer_list nums) {
// 获取可变参数长度为
std::cout << "可变参数长度为:" << nums.size() << std::endl;
std::cout << std::endl;
// 遍历输出可变参数,方法1
for (const T& i: nums) {
std::cout << i << " ";
}
std::cout << std::endl;
}
int main() {
printNumbers({"1","qq"});
printNumbers({1, 2, 3});
}
#include
using namespace std;
void print() {
cout << endl;
}
template
void print(const T& t) {
cout << t << endl;
}
template
void print(const First& first, const Rest&... rest) {
cout << first << ", ";
print(rest...); // recursive call using pack expansion syntax
}
int main()
{
print(); // calls first overload, outputting only a newline
print(1); // calls second overload
// these call the third overload, the variadic template,
// which uses recursion as needed.
print(10, 20);
print(100, 200, 300);
print("first", 2, "third", 3.14159);
}
使用这种方法,可变参数可以是任意类型的,不需要都统一是一个类型了。
这种方法需要提供一个参数包展开的函数和一个递归终止函数,二者同名。递归终止函数的参数可以为0,1,2或者多个(一般用到0个或1个),当参数包中剩余的参数个数等于递归终止函数的参数个数时,就调用递归终止函数,则函数终止。
#include
template
void prints(Args... args) {
//注意args在前,省略号在后否则报错
//std::cout <
折叠表达式是C++17 才引入的新特性,使用折叠表达式可以很方便实现展开可变参数,但是可读性也会大打折扣。在此使用的是折叠表达式的逗号运算符。折叠表达式还会分为左折叠和右折叠。
#include
#include
// 终止条件:当索引等于元组大小时
template
typename std::enable_if::value, void>::type
printtp(const Tuple&) {
// 空实现,递归终止
}
// 递归展开:当索引小于元组大小时
template
typename std::enable_if::value, void>::type
printtp(const Tuple& t) {
std::cout << std::get(t) << std::endl; // 打印当前元素
printtp(t); // 递归调用下一个索引
}
// 包装函数:将参数包转换为元组并调用printtp
template
void print(Args... args) {
printtp(std::make_tuple(args...));
}
int main() {
print(1, "hello", 3.14); // 输出:1\nhello\n3.14
return 0;
}
在这使用了std::tuple数据结构以及类型萃取中常用的std::enable_if。其实本质上还是递归模板参数展开,用起来可能不如直接使用上述方法三。
本文参考:
https://zhuanlan.zhihu.com/p/684295744
C++17常用新特性(十一)---折叠表达式-腾讯云开发者社区-腾讯云
省略号和可变参数模板 | Microsoft Learn
https://zhuanlan.zhihu.com/p/731232067
C++中神奇的tuple:详解使用技巧和实例解析-腾讯云开发者社区-腾讯云
C++之std::enable_if_std enable if-CSDN博客
c++11——可变参数模板 - 农民伯伯-Coding - 博客园