数量不定的模板参数,后续可添加任意类型参数,函数内部递归调用,逐一取出每个元素
注意点 :
1、... 就是一个pack(包),要注意三个 ... 的位置。①模板参数包 ②函数参数类型包 ③函数参数包
2、需要一个空的重载函数来应对最后一次函数递归参数为空的情况
3、 sizeof...(包参数名) 可知包内参数个数
示例1:
//空重载函数
void myPrint() {}
template <typename T, typename... Types>
void myPrint(const T& x, const Types&... args) {
cout << x << endl; //具体实现
myPrint(args...); //递归调用
}
void test() {
myPrint('a', 10, 1.11);
}
结果:
示例2:自实现printf
//自实现pringf函数
void myPrint(const char* s) {
while (*s) {
if (*s == '%' && *(++s) != '%')
throw runtime_error("invaild format");//传入参数不够
cout << *s++;
}
}
template<typename T, typename... vals>
void myPrint(const char* s, T value, vals... args) {
while (*s) {
if (*s == '%' && *(++s) != '%') {
cout << value;
myPrint(++s, args...);
return;
}
cout << *s++;//正常运行不会到这,防止因错误传入过多参数陷入死循环
}
throw logic_error("extra arguments");//传入参数太多
}
void test() {
myPrint("%d\nhh", 10);
}
示例3:递归继承,实现tuple容器
template<typename... Values> class myTuple; //声明
template<> class myTuple<> {}; //递归到最后的空类
template<typename Head, typename... Tail>
class myTuple<Head, Tail...>
: private myTuple<Tail...> {
public:
typedef myTuple<Tail...> inherited;
myTuple(){}
myTuple(Head v, Tail... vTail)
: m_Head(v), inherited(vTail...) {} //inherited(vTail...) 调用构造函数实现递归
Head head() { return m_Head; }
inherited& tail() { return *this; } //返回时转换类型到 myTuple<Tail...>
protected:
Head m_Head;
};
void test() {
myTuple<int, float, string> t(10, 10.10, "hello");
cout << t.head() << endl;
cout << t.tail().head() << endl;
cout << t.tail().tail().head() << endl;
}