简介
模板参数包是可以接受零个或多个模板参数(非类型、类型或模板)的模板参数。
1. 语法
(1) 非类型模板参数包:
ConcreteType... Args
此处 ConcreteType 为具体的类型,如 int .
(2) 类型模板参数包:
typename... Types
(3) 模板模板参数包:(即模板形参是另一个模板)
template <parameter-list> typename... Types
(4) 参数包扩展:
pattern...
将 pattern 扩展为以逗号分隔的列表(包含0或多个模式). 其中,pattern 必须包含至少一个参数包.
在类模板中,模板参数包需是最后一个模板形参. 而在函数模板中则不必(指的是在模板形参列表中的位置,而不是函数形参列表),只要能够从函数实参列表推断出参数包即可.
template<typename... Ts, typename U> struct Invalid;
template<typename... Ts, typename U, typename=void>
void valid(U, Ts...);
从上例中可以看出,即使是在函数模板中,参数包仍需要是函数形参列表的最后一个参数. 简单起见,尽量将参数包放在最后.
例子1:
template<typename... Ts>
void f(Ts...) {}
template<typename... Ts, int... N>
void g(Ts (&...arr)[N]) {}
int n[1];
g<const char, int>("a", n);
注意:不允许使用 Ts (&...)[N] ,因为 C++11 语法要求圆括号括起的 ... 需要有一个名字.
例子2:
#include <iostream>
void myPrintf(const char* fmt)
{
std::cout << fmt;
}
template <typename T, typename... Ts>
void myPrintf(const char* fmt, T value, Ts... args)
{
for (; *fmt != '\0'; fmt++)
{
if (*fmt == '%')
{
std::cout << value;
myPrintf(fmt+1, args...);
return;
}
std::cout << *fmt;
}
}
int main()
{
myPrintf("Hello, I'm %, % yeas old.", "gzming", 20);
}
Hello, I'm gzming, 20 yeas old.
2. 参数包扩展
-
当 pattern 中包含多个参数包时,这些参数包的长度应该一致. template<typename...> struct Tuple {};
template<typename T1, typename T2> struct Pair {};
template<class ...Args1> struct zip
{
template<class ...Args2> struct with
{
typedef Tuple<Pair<Args1, Args2>...> type;
};
};
typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
-
当参数包嵌套时,内层的参数包先扩展,然后再和外层的参数包一起扩展. template<class... Args>
void g(Args... args)
{
f(h(args...) + args...);
}
参数包扩展可在如下地方使用:
-
模板形参列表 template<typename... T>
struct value_holder
{
template<T... Values>
struct apply {};
};
-
模板实参列表 template<class A, class B, class...C>
void func(A arg1, B arg2, C...arg3)
{
container<A, B, C...> t1;
container<C..., A, B> t2;
container<A, C..., B> t3;
}
-
函数形参列表 template<typename ...Ts>
void f(Ts...) {}
-
函数实参列表 f(&args...);
f(++args..., n);
f(const_cast<const Args*>(&args)...);
-
圆括号初始化器 Class c1(&args...);
-
花括号初始化器 template<typename... Ts> void func(Ts... args) {
const int size = sizeof...(args) + 2;
int res[size] = { 1,args...,2 };
}
sizeof... 运算符返回参数包的大小. -
基类列表、成员初始化列表 template<class... Mixins>
class X : public Mixins... {
public:
X(const Mixins&... mixins) : Mixins(mixins)... { }
};
-
Lambda 捕获 template<class... Args>
void f(Args... args) {
auto lm = [&, args...]{ return g(args...); };
lm();
}
-
sizeof... 运算符 template<class... Types>
struct count {
static const std::size_t n = sizeof...(Types);
};
|