C++templates第四章变参模板

从C++11开始,模板可以接收一组数量可变的参数。

变参模板

可以将模板参数定义成能够接收任意多个模板参数的情况,这一类模板被称为变参模板

变参模板实例

比如,可以通过调用下面代码中的 print()函数来打印一组数量和类型都不确定的参数:

1
2
3
4
5
6
7
8
#include <iostream> 
void print () {}
template<typename T, typename… Types>
void print (T firstArg, Types… args)
{
std::cout << firstArg << ’\n’; //print first argument
print(args…); // call print() for remaining arguments
}

如果传入的参数是一个或者多个,就会调用这个函数模板,这里通过将第一个参数单独声明,就可以先打印第一个参数,然后再递归的调用print()来打印剩余的参数。这些被称为args的剩余参数,是一个函数参数包((function parameter pack) :

1
void print (T firstArg, Types… args)

调用解析:

比如,这样一个调用:

1
2
std::string s("world");
print (7.5, "hello", s);

输出如下:

1
2
3
7.5
hello
World
  1. 首先被调用为:

    print<double, char const*, std::string> (7.5, "hello", s);

  2. 打印了7.5之后,扩展为:

    print<char const*, std::string> ("hello", s);

  3. 打印了hello之后,继续调用:

    print<std::string> (s);

  4. 最后调用不接受参数的print(),结束

变参和非变参模板的重载

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream> 
template<typename T>
void print (T arg)
{
std::cout << arg << ’\n’; //print passed argument
}

template<typename T, typename… Types>
void print (T firstArg, Types… args)
{
print(firstArg); // call print() for the first argument
print(args…); // call print() for remainingarguments
}

也就是说,当两个函数模板的区别只在于尾部的参数包的时候会优先选择没有尾部参数包的那一个函数模板。

总结

  • 通过使用参数包,模板可以有任意多个任意类型的参数。
  • 为了处理这些参数,需要使用递归,而且需要一个非变参函数终结递归(如果使用编译期判断,则不需要非变参函数来终结递归)。
  • 运算符 sizeof…用来计算参数包中模板参数的数目。
  • 变参模板的一个典型应用是用来发送(forward)任意多个任意类型的模板参数。
  • 通过使用折叠表达式,可以将某种运算应用于参数包中的所有参数。