建网站优势,西安优秀的定制网站建设公司哪家好,拖拽网站,缅甸新闻最新消息【导读】#xff1a;C 可变参数模板对参数进行了高度泛化#xff0c;它能表示0到任意个数、任意类型的参数。相比C98/03#xff0c;类模版和函数模版中只能含固定数量的模版参数#xff0c;可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象#xff0c;使用…【导读】C 可变参数模板对参数进行了高度泛化它能表示0到任意个数、任意类型的参数。相比C98/03类模版和函数模版中只能含固定数量的模版参数可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象使用起来需要一定的技巧所以它也是C11中最难理解和掌握的特性之一。那么请大家跟随小编一起来学习吧。 以下是正文 概述 在C11之前类模板和函数模板只能含有固定数量的模板参数。C11增强了模板功能允许模板定义中包含0到任意个模板参数这就是可变参数模板。 可变参数模板和普通模板的语义是一样的只是写法上稍有区别声明可变参数模板时需要在typename或class后面带上省略号“…” //T叫模板参数包args叫函数参数包templateclass ... T void func(T ... args){//可变参数模板函数}func(); // OKargs不含有任何实参func(1); // OKargs含有一个实参intfunc(2, 1.0); // OKargs含有两个实参int和double
T叫模板参数包args叫函数参数包。 省略号“…”的作用有两个 1声明一个参数包这个参数包中可以包含0到任意个模板参数 2在模板定义的右边可以将参数包展开成一个一个独立的参数 可变参数模板函数 可变参数模板函数的定义 一个可变参数模板函数的定义如下 #include iostreamusing namespace std;templateclass ... T void func(T ... args){//可变参数模板函数 //sizeof...sizeof后面有3个小点计算变参个数 cout num sizeof...(args) endl;}int main(){ func(); // num 0 func(1); // num 1 func(2, 1.0); // num 2 return 0;} 运行结果如下参数包的展开 递归方式展开 通过递归函数展开参数包需要提供一个参数包展开的函数和一个递归终止函数。 #include iostreamusing namespace std;//递归终止函数void debug(){ cout empty\n;}//展开函数template class T, class ... Argsvoid debug(T first, Args ... last){ cout parameter first endl; debug(last...);}int main(){ debug(1, 2, 3, 4); return 0;} 运行结果如下
递归调用过程如下 debug(1, 2, 3, 4);debug(2, 3, 4);debug(3, 4);debug(4);debug(); 通过可变参数模板实现打印函数 #include iostream#include stdexceptusing namespace std;void Debug(const char* s){ while (*s) { if (*s % *s ! %) { throw runtime_error(invalid format string: missing arguments); } cout *s; }}templatetypename T, typename... Argsvoid Debug(const char* s, T value, Args... args){ while (*s) { if (*s % *s ! %) { cout value; return Debug(s, args...); } cout *s; } throw runtime_error(extra arguments provided to Debug);}
int main(){ Debug(a %d, b %c, c %s\n, 250, m, mike); return 0;} 运行结果如下
非递归方式展开 #include iostreamusing namespace std;template class Tvoid print(T arg){ cout arg endl;}template class ... Argsvoid expand(Args ... args){ int a[] { (print(args), 0)... };}int main(){ expand(1, 2, 3, 4); return 0;}
运行结果如下
expand函数的逗号表达式(print(args), 0) 也是按照这个执行顺序先执行print(args)再得到逗号表达式的结果0。 同时通过初始化列表来初始化一个变长数组{ (print(args), 0)… }将会展开成( (print(args1), 0), (print(args2), 0), (print(args3), 0), etc…), 最终会创建一个元素只都为0的数组int a[sizeof…(args)]。 可变参数模板类 继承方式展开参数包 可变参数模板类的展开一般需要定义2 ~ 3个类包含类声明和特化的模板类
#include iostream#include typeinfousing namespace std;templatetypename... A class BMW{}; // 变长模板的声明templatetypename Head, typename... Tail // 递归的偏特化定义class BMWHead, Tail... : public BMWTail...{//当实例化对象时则会引起基类的递归构造public: BMW() { printf(type: %s\n, typeid(Head).name()); } Head head;};template class BMW{}; // 边界条件int main(){ BMWint, char, float car; return 0;} 运行结果如下
模板递归和特化方式展开参数包
#include iostreamusing namespace std;template long... nums struct Multiply;// 变长模板的声明template long first, long... laststruct Multiplyfirst, last... // 变长模板类{ static const long val first * Multiplylast...::val;};templatestruct Multiply // 边界条件{ static const long val 1;};int main(){ cout Multiply2, 3, 4, 5::val endl; // 120 return 0;} 运行结果如下
- EOF -