C++笔记-Variadic Templates

C++笔记-Variadic Templates

C++ 11引入了可变参数模板,使得用户可以实现传入未知数目且未知数据类型参数的函数。

1. Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
using namespace std;

void printxx(){};

template<typename T, typename... Types>
void printxx(const T& firstArg, const Types&... Args){
cout << firstArg << endl;
cout << "sizeof package" << ' '<<sizeof...(Args)<< endl;
printxx(Args...);
}

int main(){
printxx(1.7, "bad",7,9,0);
return 0;
}

printxx函数包含两个参数firstArg和 Args,Args是一个包(package),可以包含任意数目任意类型的参数,因此我们需要使用递归的方法来使用可变参数模板。

我们可以使用sizeof…(Args)来获取当前包的大小。当我们调用printxx函数的时候,1.7作为firstArg被输出,Args包含其余三个元素,然后递归调用printxxx。由于递归终点是参数为空,而printxx需要至少有一个参数,因此,我们需要重新写一个不含参数的printxx函数。

2. 调用规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<tuple>
using namespace std;

void printxx(){};

template<typename T, typename... Types>
void printxx(const T& firstArg, const Types&... Args){
cout << "Call A" << endl;
}
template<typename T, typename... Types>
void printxx(const char* firstArg, const T& secondArg, const Types&... Args){
cout << "Call C" << endl;
}
template<typename... Types>
void printxx(const Types&... Args){
cout << "Call B"<< endl;
}

int main(){
printxx("1","2",7,9,0);
return 0;
}

对于该程序,输出结果为”Call C”,这是因为函数会调用特化最强的,而不是泛化最强的。也即对于所有满足条件的函数,会调用参数最细化的。

3. 应用

C++中的tuple, unordered容器就是用Variadic Template实现的。