
解释
C++03只有固定模板参数。C++11 加入新的表示法,允许任意个数、任意类别的模板参数,不必在定义时将参数的个数固定。
变长模板、变长参数是依靠C++11新引入的参数包的机制实现的。
参数包
-
一个模板形参包(template parameter pack)是一个接受零个或多个模板实参的模板形参。
template<class ... Types> struct Tuple { };Tuple<> t0; // Types不含任何实参Tuple<int> t1; // Types含有一个实参:intTuple<int, float> t2; // Types含有两个实参:int和floatTuple<0> error; // 错误:0不是一个类型
-
一个函数形参包(function parameter pack)是一个接受零个或多个函数实参的函数形参
template<class ... Types> void f(Types... args);f(); // OK:args不含有任何实参f(1); // OK:args含有一个实参:intf(2, 1.0); // OK:args含有两个实参int和double
-
一个形参包要么是一个模板形参包,要么是一个函数形参包。
-
一个包扩展(expansion)由一个模式(pattern)和一个省略号组成。包扩展的实例中一个列表中产生零个或多个模式的实例。模式的形式依赖于扩展所发生的上下文中
template <typename... TS> // typename... TS为模板形参包,TS为模式static void MyPrint(const char* s, TS... args) // TS... args为函数形参包,args为模式{printf(s, args...);}
解包
一个常用的技巧是:利用模板推导机制,每次从参数包里面取第一个元素,缩短参数包,直到包为空。
template <typename T>void fun(const T& t){cout << t << '\n';}template <typename T, typename ... Args>void fun(const T& t, Args ... args){cout << t << ',';fun(args...);//递归解决,利用模板推导机制,每次取出第一个,缩短参数包的大小。}
在C++17标准中,可以使用fold expression,更直接地表达,并且确保正序展开:
// C++17template<typename T0, typename... T>void printf(T0 t0, T... t) {std::cout << t0 << std::endl;if constexpr (sizeof...(t) > 0) printf(t...);}// C++11#include <iostream>template <typename T0>void printf(T0 value){std::cout << value << std::endl;}template <typename T, typename... Args>void printf(T value, Args... args){std::cout << value << std::endl;printf(args...);}int main(){printf(1, 2, "123", 1.1);return 0;}
关注公众号获取更多信息:

本文介绍了C++11中的变长模板特性,包括模板形参包、函数形参包的概念及其应用实例,展示了如何通过递归模板来处理变长参数包,并对比了C++17中对这一特性的改进。
4990

被折叠的 条评论
为什么被折叠?



