一、可变参数模版【c++11】
-
c++11之前,模版template,只能使用固定的参数数量。
-
但是可变模版可以让你拥有多个各种类型的参数。
-
我们把带省略号的参数称为参数包,参数包里面可以包含0到N 个模板参数,而args则是一个函数形参参数包。
-
模版一如下,使用递归展开
// 递归终止条件
void print() { cout << endl; }
//🍎 基本语法:typename... Args 表示可变参数包
template<typename T, typename... Args> // Args是类型参数包
void print(T first, Args... rest) { // rest是值参数包cout << first << " ";print(rest...); // 递归展开参数包
}//📌 使用示例
print(1, 3.14, "hello"); // 输出:1 3.14 hello
- 模版二如下,使用if constexpr结合sizeof…(args)的方式展开
template<class T,class...U >void test(T first,U...others){cout<<first<<endl;if constexpr (sizeof...(others)>0){test(others...);}}
int main(){test(11,22,33,44,55,66);//11 22 33 44 55
}
-
核心特点:允许函数/类接受任意数量/类型的参数,是C++11引入的重要特性。
-
统计参数数量的方式
template<typename... Args>
void countArgs(Args... args) {cout << sizeof...(args) << endl; // 关键符sizeof...
}
二、折叠表达式【c++17】
1、了解
- 一共就4种形式
- 本质作用:提供单行表达式展开参数包的能力,取代传统的递归展开方式,代码更简洁、性能更好。
- op是二元操作符
- args是参数包
- init是初始值。
折叠表达式支持所有C++中的二元操作符,包括但不限于:(了解一下就行了)
算术运算符:+, -, *, /, %
逻辑运算符:&&, ||
比较运算符:==, !=, <, >, <=, >=
位运算符:&, |, ^, <<, >>
2、左折叠
- 从第一个元素开始
#include<iostream>
#include<cstdio>
using namespace std;template <class ...Args>
auto sum(Args...args){return (args+...);
}
int main(){int s=sum(1,2,3,4,5);printf("%d",s);//15=((((1+2)+3)+4)+5)
}
3、右折叠
- 从最后一个元素开始
template <class ...Args>
auto sum(Args...args){return (...+args);
}
int main(){int s=sum(1,2,3,4,5);printf("%d",s);//15=(1+(2+(3+(4+5))))
}
4、左折叠带初始
- 操作开始时,有个初始值
template <typename T,class ...Args>
auto sum(T init,Args...args){int s= ((init)+...+args);return s;
}
int main(){int s=sum((1*10),1,2,3,4,5);printf("%d",s);//25
}
5、右折叠带初始
- 操作结束时,有个初始值
template <typename T,class ...Args>
auto sum(T init,Args...args){int s= (args+...+(init));return s;
}
int main(){int s=sum((1*10),1,2,3,4,5);printf("%d",s);//25
}
6、注意
- 带初始的折叠,左右2边 op 符号要一致
- 可以使用 sizeof …(args)获取 参数数量
- init 里有 op符号的话,要把它们括起来 比如 init 是 1 * 2,就要写成 (args +…+(1 * 2))