赞
踩
在C++中,我们可以使用可变参数模板函数来实现接受可变个数参数的函数。
可变参数模板函数的基本语法如下:
template <typename T,typename... Args>
返回值类型 函数名(T first, Args... args) {
// 函数体
}
其中T
是命名参数的类型,Args...
表示参数包,args
是参数包的名字。在函数体中,我们可以通过args
来访问传递进来的参数。
可以使用递归来逐个访问参数包中的每个元素:
template<typename T> void Print(const T& str){//特化 cout << str << endl; } template <typename T, typename... Args> void Print(T& first, Args&&... args) { cout << first; Print(forward<Args>(args)...);//完美转发 } //上面的模板也可以不用完美转发 //void Print(T& first, Args... args) { // cout << first; // Print(args...); //} int main(){ Print("hello "); Print("hello ", "你好 "); Print("hello ", "你好 ","666"); return 0; }
递归展开参数包可以访问每个参数,但代码较复杂。假设我们执行最下面的Print(“hello”,“你好”,“666”),程序的执行逻辑是:调用模板函数,hello
传给first
,后面两个实参传给可变参数包
输出结果:
将参数包存入std::tuple
,然后用std::get
访问每个元素:
template <typename... Args>
void print(Args... args) {
auto t = make_tuple(args...);
cout << get<0>(t) << endl;
cout << get<1>(t) << endl;
// ...
}
这种方法代码简洁,但需要知道每个参数的类型和序号。
#include <iostream> #include <tuple> template <typename... Args> void parse(Args... args) { auto tup = make_tuple(args...); cout << get<3>(tup) << endl; //get不能这么用,get中的<>里面的值得是const的 //auto tup = make_tuple(args...); //for(auto i=1;i<get<0>(tup);i++){ // cout << get<i>(tup) << endl; //} } int main() { parse(1, 2, 3, 4, 5); return 0; }
程序输出:
4
这种展开参数包的方式,不需要通过递归终止函数,是直接在展开函数的函数体中展开的, printarg
不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。展开函数中的逗号表达式:(printarg(args), 0)
,也是按照这个执行顺序,先执行printarg(args)
,再得到逗号表达式的结果0。同时还用到了C++11的另外一个特性——初始化列表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)...}
将会展开成((printarg(arg1),0),(printarg(arg2),0)
, (printarg(arg3),0),...)
,最终会创建一个元素值都为0的数组int arr[sizeof...(Args)]
。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)
打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在数组构造的过程展开参数包.
template <class T> void PrintArg(T t){ cout << t << " "; } //展开函数 template <class ...Args> void ShowList(Args... args){ int arr[] = { (PrintArg(args), 0)... }; cout << endl; } int main(){ ShowList(1); ShowList(1, 'A'); ShowList(1, 'A', std::string("sort")); return 0; }
在下方代码中,fun_
函数直接讲参数包传递给fun,fun
函数则会讲args
参数包依次展开对应其形参
void fun(int a, char b)
{
cout << a << b << endl;
}
template <class ...Args>
void fun_(Args ...args)
{
fun(args...);
}
int main()
{
fun_(3,'a');
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。