可变参数模板
一、可变参数模板
template <typename T, typename ... Args> void fun(T t, Args ... args);//合法 template <typename ... Args, typename T> void fun(Args ... args, T t);//非法
1 // Args是一个模板参数包; rest是一个函数参数包 2 // Args表示零个或多个模板类型参数 3 // rest表示林个或多个函数参数 4 template <typename T, typename ... Args> 5 void foo(const T &t, const Args& ... rest) 6 7 int i = 0; double d = 3.14; strng s = "how now brown cow"; 8 foo(i, s, 42, d); 9 foo(s, 42, "hi"); 10 foo(d, 42); 11 foo("hi"); 12 13 void foo(const int&, const string&, const int&, const double&); 14 void(const string&, const int&, const char[3]&); 15 void foo(const double&, const string&); 16 void foo(const char[3]&);
二、sizeof...运算符
【注意】当我们需要知道包中有多少个元素时,可以用sizeof...
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 template <typename T, typename ... Args> 6 void foo(const T&, const Args& ... rest) 7 { 8 cout << sizeof...(Args) << " "; //模板类型参数的数目 9 cout << sizeof...(rest) << endl; // 函数参数的数目 10 } 11 12 int main() 13 { 14 int i = 0; double d = 3.14; string s = "how now brown cow"; 15 foo(i, s, 42, d); 16 foo(s, 42, "hi"); 17 foo(d, 42); 18 foo("hi"); 19 20 return 0; 21 }
运行结果:
三、编译可变参数函数模板
非可变参数模板比可变参数模板更特例化,因此编译器选择非可变参数版本。
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 template <typename T> 6 ostream& print(ostream &os, const T &t) 7 { 8 return os << t << endl; 9 } 10 11 template <typename T, typename ... Args> 12 ostream &print(ostream &os, const T &t, const Args& ... rest) 13 { 14 os << t << " , "; 15 return print(os, rest ...); 16 } 17 18 int main() 19 { 20 int i = 0; 21 string s = "hello"; 22 23 print(cout, i); 24 print(cout, i, s); 25 print(cout, i, s, 42.1, 'A', "End"); 26 return 0; 27 }
运行结果:
练习16.55
四、包扩展
1 #include <iostream> 2 using namespace std; 3 4 template <typename T> 5 T accum(const T &t) 6 { 7 return t; 8 } 9 10 template <typename T, typename... Args> 11 T accum(const T &t, Args... args) 12 { 13 return t + accum(args...); 14 } 15 16 int h() 17 { 18 return 42; 19 } 20 21 template <typename ...Args> 22 int h(int t, Args ... args) 23 { 24 return t + h(args...); 25 } 26 27 void f(int i, int j = 0, int k = 0, int l = 0) 28 { 29 cout << i << " + " 30 << j << " + " 31 << k << " + " 32 << l << " = " 33 << i + j + k + l << endl; 34 } 35 36 template<typename ... Args> 37 void g(Args ... args) 38 { 39 cout << sizeof...(Args) << endl; 40 cout << sizeof...(args) << endl; 41 // h(a1, a2, a3, ..., an) 42 f(args...); 43 // h(a1, a2, a3, ..., an) 44 cout << h(args...) << endl; 45 //f(h(a1), h(a2), h(a3), ..., h(an)) 46 f(h(args) ...); 47 // f(h(a1, a2, a3, ..., an2) 48 f(h(args ...)); 49 // f(h(5,6,7,8) + a1, h(5,6,7,8) + a2, h(5,6,7,8) + a3, ..., h(5,6,7,8) + an) 50 f(h(5, 6, 7, 8) + args ...); 51 } 52 53 int main() 54 { 55 cout << accum(1, 2, 3, 4) << endl; 56 g(1, 2, 3, 4); 57 return 0; 58 }
运行结果:
五、转发参数包
模板特例化
1. 全特化就是全部特化,即针对所有的模板参数进行特化。
2. 偏特化就是部分特化,即针对部分模板参数进行特化。
全特化和偏特化的定义不是很严格,所以有的时候不容易让人理解。
1 #include <iostream> 2 using namespace std; 3 4 namespace templateTest { 5 6 //模版泛化 7 template<typename T> 8 class iterator_traits 9 { 10 public: 11 iterator_traits() 12 { 13 cout << "模版泛化" << endl; 14 } 15 16 ~iterator_traits() 17 { 18 19 } 20 }; 21 22 //偏特化 23 template<typename T> 24 class iterator_traits<T*> 25 { 26 public: 27 iterator_traits() 28 { 29 cout << "模版偏特化,特化常规指针" << endl; 30 } 31 32 ~iterator_traits() 33 { 34 35 } 36 }; 37 38 //偏特化 39 template<typename T> 40 class iterator_traits<const T*> 41 { 42 public: 43 iterator_traits() 44 { 45 cout << "模版偏特化,特化const指针" << endl; 46 } 47 48 ~iterator_traits() 49 { 50 51 } 52 }; 53 54 //全特化 55 template<> 56 class iterator_traits<int> 57 { 58 public: 59 iterator_traits() 60 { 61 cout << "模版全特化int类型" << endl; 62 } 63 64 ~iterator_traits() 65 { 66 67 } 68 }; 69 }; 70 71 //泛化 72 template<class U, class T> 73 class Test 74 { 75 public: 76 Test() 77 { 78 cout << "Test 泛化" << endl; 79 } 80 }; 81 82 //偏特化 83 template< class T> 84 class Test<int, T> 85 { 86 public: 87 88 Test() 89 { 90 cout << "Test 偏特化" << endl; 91 } 92 }; 93 94 //全特化 95 template<> 96 class Test<int, char> 97 { 98 public: 99 100 Test() 101 { 102 cout << "Test 全特化" << endl; 103 } 104 }; 105 template<typename T> 106 void max(const T& t1, const T & t2) 107 { 108 cout << "模版函数泛化" << endl; 109 110 } 111 112 //其实函数模版不存在偏特化,只有全特化 113 template<> 114 void max<int>(const int& t1, const int& t2) 115 { 116 cout << "模版函数特化" << endl; 117 } 118 119 void main() 120 { 121 templateTest::iterator_traits<int> t1; 122 templateTest::iterator_traits<float> t2; 123 templateTest::iterator_traits<int *> t3; 124 templateTest::iterator_traits<const int *> t4; 125 Test<int, int> t5; 126 Test<float, int> t6; 127 Test<int, char> t7; 128 max(5, 10); 129 max(5.5, 10.5); 130 system("pause"); 131 }
运行结果: