【C++编程】模板与泛型编程 | 定义模板

 Blob类

 1 #include<iostream>
 2 #include<initializer_list>
 3 #include<vector>
 4 using namespace std;
 5 
 6 template <typename T> 
 7 class Blob {
 8 public:
 9     typedef typename vector<T>::size_type size_type;
10 
11     Blob();
12     Blob(initializer_list<T> il);
13     size_type size() const { return data->size(); }
14     bool empty() const { return data->empty(); }
15     void push_back(const T &t) { data->push_back(t); }
16     void push_back(T &&t) { data->push_back(std::move(t)); }
17     void pop_back();
18     T& back();
19     T& operator[](size_type i);
20 
21 private:
22     shared_ptr<vector<T>> data;
23     void check(size_type i, const string &msg) const;
24 };
25 
26 template <typename T>
27 void Blob<T>::check(size_type i, const string &msg) const
28 {
29     if (i >= data->szie())
30         throw out_of_range(msg);
31 }
32 
33 template <typename T>
34 Blob<T>::Blob() : data(make_shared<vector<T>>()) {}
35 
36 template <typename T>
37 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {}
38 
39 template <typename T>
40 T& Blob<T>::back()
41 {
42     check(0, "back on empty Blob");
43     return data->back();
44 }
45 
46 template <typename T>
47 T& Blob<T>::operator[](size_type i)
48 {
49     check(i, "subscript out of range");
50     return (*data)[i];
51 }
52 
53 template <typename T>
54 void Blob<T>::pop_back()
55 {
56     check(0, "pop_back on emppty Blob");
57     data->pop_back();
58 }
View Code

 

 

BlobPtr类

头文件

  1 /********BlobPtr*********/
  2 
  3 #ifndef BLOBPTR_H
  4 #define BlOBPTR_H
  5 #include<iostream>
  6 #include<initializer_list>
  7 #include<string>
  8 #include<memory>
  9 #include<vector>
 10 using namespace std;
 11 
 12 template <typename> class BlobPtr;  //前置声明, 在Blob申明友元所需要的
 13 template <typename> class Blob;     //前置申明,运算符==中的参数所需要的
 14 template <typename T>
 15 bool operator==(const Blob<T>&, const Blob<T>&);
 16 
 17 template <typename T>
 18 class Blob {
 19     friend class BlobPtr<T>;
 20     friend bool operator ==<T>(const Blob<T>&, const Blob<T>&);
 21 public:
 22     typedef typename vector<T>::size_type size_type;
 23 
 24     Blob();
 25     Blob(initializer_list<T> il);
 26     size_type size() const { return data->size(); }
 27     bool empty() const { return data->empty(); }
 28     void push_back(const T &t) { data->push_back(t); }
 29     void push_back(T &&t) { data->push_back(std::move(t)); }
 30     void pop_back();
 31     T& back();
 32     T& operator[](size_type i);
 33 
 34     BlobPtr<T> begin() { return BlobPtr<T>(*this); }
 35     BlobPtr<T> end()
 36     {
 37         auto ret = BlobPtr<T>(*this, data->size());
 38         return ret;
 39     }
 40 private:
 41     shared_ptr<vector<T>> data;
 42     void check(size_type i, const string &msg) const;
 43 };
 44 
 45 template <typename T>
 46 void Blob<T>::check(size_type i, const string &msg) const
 47 {
 48     if (i >= data->szie())
 49         throw out_of_range(msg);
 50 }
 51 
 52 template <typename T>
 53 Blob<T>::Blob() : data(make_shared<vector<T>>()) {}
 54 
 55 template <typename T>
 56 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {}
 57 
 58 template <typename T>
 59 T& Blob<T>::back()
 60 {
 61     check(0, "back on empty Blob");
 62     return data->back();
 63 }
 64 
 65 template <typename T>
 66 T& Blob<T>::operator[](size_type i)
 67 {
 68     check(i, "subscript out of range");
 69     return (*data)[i];
 70 }
 71 
 72 template <typename T>
 73 void Blob<T>::pop_back()
 74 {
 75     check(0, "pop_back on emppty Blob");
 76     data->pop_back();
 77 }
 78 
 79 template <typename T>
 80 bool operator==(const Blob<T> &lhs, const Blob<T> &rhs)
 81 {
 82     if (rhs.size() != lhs.size())
 83         return false;
 84     for (size_t i = 0; i != lhs.size(); +i)
 85         if (lhs[i] != rhs[i])
 86             return false;
 87     return true;
 88 }
 89 
 90 /******************************************************************/
 91 
 92 template <typename T>
 93 bool operator==(const BlobPtr<T>&, const BlobPtr<T>&);
 94 
 95 template <typename T>
 96 class BlobPtr {
 97     friend bool operator==<T>(const BlobPtr<T>&, const BlobPtr<T>&);
 98 public:
 99     BlobPtr() : curr(0) {}
100     BlobPtr(Blob<T> &a, size_t sz = 0) : wptr(a.data), curr(sz) {}
101     
102     T& operator*() const;
103 
104     BlobPtr& operator++();       //前置运算符
105     BlobPtr& operator--();       //前置运算符
106     BlobPtr operator++(int);     //后置运算符
107     BlobPtr operator--(int);     //后置运算符
108 private:
109     shared_ptr<vector<T>> check(size_t, const string &) const;
110     weak_ptr<vector<T>> wptr;
111     size_t curr;  //数组当前的位置
112 };
113 
114 template <typename T>
115 shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string &msg) const
116 {
117     auto ret = wptr.lock();
118     if (!ret)
119         throw std::runtime_error("unbound BlobPtr");
120     if (i >= ret->size())
121         throw std::out_of_range(msg);
122     return ret;
123 }
124 
125 template <typename T>
126 T& BlobPtr<T>::operator*() const
127 {
128     auto p = check(curr, "dereference past end");
129     return (*p)[curr];
130 }
131 
132 template <typename T>
133 BlobPtr<T> BlobPtr<T>::operator++(int) //++后置运算符
134 {
135     BlobPtr ret = *this;
136     ++*this;
137     return ret;
138 }
139 
140 template <typename T>
141 BlobPtr<T> BlobPtr<T>::operator--(int) //--后置运算符
142 {
143     BlobPtr ret = *this;
144     --*this;
145     return ret;
146 }
147 
148 template <typename T>
149 BlobPtr<T>& BlobPtr<T>::operator++() //++前置运算符
150 {
151     check(curr, "increment past end of BlobPtr");
152     ++curr;
153     return *this;
154 }
155 
156 template <typename T>
157 BlobPtr<T>& BlobPtr<T>::operator--() //--前置运算符
158 {
159     --curr;  //如果是0,则继续递减它产生一个无效下标
160     check(curr, "decrement past begin of BlobPtr");
161     return *this;
162 }
163 
164 template <typename T>
165 bool operator == (const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
166 {
167     return (lhs.wptr.lock().get() == rhs.wptr.lock().get()) && lhs.curr == rhs.curr;
168 }
169 
170 template <typename T>
171 bool operator!=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
172 {
173     return !(rhs == lhs);
174 }
175 #endif
View Code

主函数

 1 #include<iostream>
 2 #include<string>
 3 #include"BlobPtr.h"
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     Blob<string> b1;
 9     cout << b1.size() << endl;
10     {
11         Blob<string> b2 = { "a", "an", "the" };
12         b1 = b2;
13         b2.push_back("about");
14         cout << b1.size() << " " << b2.size() << endl;
15     }
16     cout << b1.size() << endl;
17     for (auto p = b1.begin(); p != b1.end(); ++p)
18         cout << *p << " ";
19     return 0;
20 }
View Code

输出结果:

 

 

成员模板 

1. 若外围类定义也是类模板,则在类体外定义成员模板时,它接收二个模板形参集:一个是外围类的,另一个是自身的:

 1 template<typename T1>
 2 struct string 
 3 {
 4     // 成员模板函数
 5     template<typename T2>
 6     int compare(const T2&);
 7 
 8     // 构造函数亦可为模板
 9     template<typename T2>
10     string(const std::basic_string<T2>& s) { /*...*/ }
11 };
12 
13 // string<T1>::compare<T2> 的类外定义 
14 template<typename T1> // 对于外围类模板
15 template<typename T2> // 对于成员模板
16 int string<T1>::compare(const T2& s) { /* ... */

 

2. 可以声明拥有相同名称的非模板成员函数和模板成员函数。在冲突的情况下(某些模板特化准确匹配非模板函数的签名),该名称的使用及类型指代非模板成员,除非提供显式模板实参列表。 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 template<typename T>
 5 struct A 
 6 {
 7     void f(int); // 非模板成员
 8 
 9     template<typename T2>
10     void f(T2); // 成员模板    
11 };
12 
13 template <typename T>
14 void A<T>::f(int)
15 {
16     cout << "非模板成员" << endl;
17 }
18 
19 // 模板成员定义
20 template <typename T>
21 template <typename T2>
22 void A<T>::f(T2)
23 {
24     cout << "成员模板" << endl;
25 }
26 
27 int main()
28 {
29     A<char> ac;
30     ac.f('c'); // 调用模板函数 A<char>::f<char>(int)
31     ac.f(1);   // 调用非模板函数 A<char>::f(int)
32     ac.f<>(1); // 调用模板函数 A<char>::f<int>(int)
33     return 0;
34 }

运行结果:

 

3. 举例

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 struct Printer 
 7 { 
 8     ostream& os;
 9     Printer(ostream& os): os(os) {}
10 
11     template<typename T>
12     void operator()(const T& obj) { os << obj << ' '; } // 成员模板
13 };
14 
15 int main()
16 {
17     vector<int> v = { 1,2,3 };
18     for_each(v.begin(), v.end(), Printer(cout));
19     string s = "abc";
20     for_each(s.begin(), s.end(), Printer(cout));
21 }

运行结果:

for_each源码:

1 template<typename InputIterator, typename Function>
2 Function for_each(InputIterator beg, InputIterator end, Function f) 
3 {
4   while(beg != end) 
5     f(*beg++);
6 }
View Code

 

模板实参推断

posted @ 2018-07-25 19:31  苏格拉底的落泪  阅读(263)  评论(0编辑  收藏  举报