可变参数模板

一、可变参数模板

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 = 0double  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 }

运行结果:

003  可变参数模板

 

 

三、编译可变参数函数模板

非可变参数模板比可变参数模板更特例化,因此编译器选择非可变参数版本。

 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 }

运行结果:

003  可变参数模板

 

练习16.55

003  可变参数模板

 

 

四、包扩展

 

 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 }

运行结果:

003  可变参数模板

 

五、转发参数包

 模板特例化

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 }

运行结果:

003  可变参数模板

 

相关文章: