【C++ 模板】 可变参数模板
可变参数模板
一个可变参数模板就是一个接受可变数目参数的模板函数或模板类,可变数目的参数称作参数包 存在两种参数包:
- 模板参数包,表示零个或多个模板参数
- 函数参数包, 表示零个或多个函数参数
使用原型:
template <typename T, typename ... Args>
void fun(T t, Args ... args);// 合法
template <typename ... Args, typename T>
void fun(Args ... args, T t);// 非法
与往常一样,编译器从函数的实参推断模板参数类型。对于一个可变参数模板,编译器还会推断包中参数的数目。例如, 给定下面的调用:
// Args是一个模板参数包; rest是一个函数参数包
// Args表示零个或多个模板类型参数
// rest表示林个或多个函数参数
template <typename T, typename ... Args>
void foo(const T &t, const Args& ... rest)
int i = 0; double d = 3.14; strng s = "how now brown cow";
foo(i, s, 42, d);
foo(s, 42, "hi");
foo(d, 42);
foo("hi");
编译器会为foo 实例化出四个不同的版本:
void foo(const int&, const string&, const int&, const double&);
void(const string&, const int&, const char[3]&);
void foo(const double&, const string&);
void foo(const char[3]&);
二、sizeof...运算符
【注意】当我们需要知道包中有多少个元素时,可以用sizeof...
#include<iostream>
#include<string>
using namespace std;
template <typename T, typename ... Args>
void foo(const T&, const Args& ... rest)
{
cout << sizeof...(Args) << " "; //模板类型参数的数目
cout << sizeof...(rest) << endl; // 函数参数的数目
}
int main()
{
int i = 0; double d = 3.14; string s = "how now brown cow";
foo(i, s, 42, d);
foo(s, 42, "hi");
foo(d, 42);
foo("hi");
return 0;
}
运行结果:
1. 示例:非可变参数模板比可变参数模板更特例化,因此编译器选择非可变参数版本。
#include<iostream>
#include<string>
using namespace std;
template <typename T>
ostream& print(ostream &os, const T &t)
{
return os << t << endl;
}
template <typename T, typename ... Args>
ostream &print(ostream &os, const T &t, const Args& ... rest)
{
os << t << " , ";
return print(os, rest ...);
}
int main()
{
int i = 0;
string s = "hello";
print(cout, i);
print(cout, i, s);
print(cout, i, s, 42.1, 'A', "End");
return 0;
}
运行结果:
练习16.55
四、包扩展
#include <iostream>
using namespace std;
template <typename T>
T accum(const T &t)
{
return t;
}
template <typename T, typename... Args>
T accum(const T &t, Args... args)
{
return t + accum(args...);
}
int h()
{
return 42;
}
template <typename ...Args>
int h(int t, Args ... args)
{
return t + h(args...);
}
void f(int i, int j = 0, int k = 0, int l = 0)
{
cout << i << " + "
<< j << " + "
<< k << " + "
<< l << " = "
<< i + j + k + l << endl;
}
template<typename ... Args>
void g(Args ... args)
{
cout << sizeof...(Args) << endl;
cout << sizeof...(args) << endl;
// h(a1, a2, a3, ..., an)
f(args...);
// h(a1, a2, a3, ..., an)
cout << h(args...) << endl;
//f(h(a1), h(a2), h(a3), ..., h(an))
f(h(args) ...);
// f(h(a1, a2, a3, ..., an2)
f(h(args ...));
// f(h(5,6,7,8) + a1, h(5,6,7,8) + a2, h(5,6,7,8) + a3, ..., h(5,6,7,8) + an)
f(h(5, 6, 7, 8) + args ...);
}
int main()
{
cout << accum(1, 2, 3, 4) << endl;
g(1, 2, 3, 4);
return 0;
}
运行结果: