本文仅探讨序列式容器的选择应用,对一个类型而言,既选择了序列式容器,就意味在vector,list,deque间选择(这里要说明的是,stack和queue虽然也是序列式容器,但从真正严格意义上讲,它们只是一种适配器)那么有没有办法作一个通用的包装类提供给开发者,让开发者自己根据应用决定选择具体的容器类型呢?同时这个包装又不影响原容器的接口使用。 关于包装类的实现,代码描述如下
2 #define _STL_COLLECTION_H
3
4 #include < memory >
5 #include < vector >
6
7 /**
8 @class STLCollection
9 @brief 基于STL序列容器实现的通用集合类
10
11 * 提供以索引作为外参的以下公共通用接口
12 * add --- 向前或向后增加单个元素
13 * insert --- 插入单个元素
14 * erase --- 删除单个或多个元素
15 * set --- 修改某个元素
16 * get --- 获取某个元素
17 * front --- 获取第一个元素
18 * back --- 获取最后一个元素
19*/
20 template < typename T,template < class T, class U > class C = std::vector,template < class T > class U = std::allocator >
21 class STLCollection : public C < T,U < T > >
22 {
23 typedef U<T> Allocator;
24 typedef C<T,Allocator> base;
25
26public:
27 //为使用方便,重新定义实现构造函数及拷贝构造函数,但赋值拷贝可以不用重新定义实现
28 STLCollection()
29 {
30 }
31 explicit STLCollection(const Allocator& al)
32 :base(al)
33 {
34 }
35 explicit STLCollection(size_t n)
36 :base(n)
37 {
38 }
39 STLCollection(size_t n,const T& t)
40 :base(n,t)
41 {
42 }
43 STLCollection(size_t n,const T& t,const Allocator& al)
44 :base(n,t,al)
45 {
46 }
47 STLCollection(const STLCollection& right)
48 :base(right)
49 {
50 }
51
52 template<class InputIterator>
53 STLCollection(InputIterator first,InputIterator last)
54 :base(first,last)
55 {
56 }
57
58 template<class InputIterator>
59 STLCollection(InputIterator first,InputIterator last,const Allocator& al)
60 :base(first,last,al)
61 {
62 }
63
64public:
65 //使基类的同名函数erase,insert,front,back可见
66 using base::erase;
67 using base::insert;
68 using base::front;
69 using base::back;
70
71 void add(const T& t,bool append = true)
72 {
73 if (append)
74 base::insert(base::end(),t);
75 else
76 base::insert(base::begin(),t);
77 }
78 void insert(size_t index,const T& t)
79 {
80 insert_impl(index,t,typename std::iterator_traits<typename base::iterator>::iterator_category());
81 }
82 void erase(size_t index)
83 {
84 erase_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
85 }
86 void erase(size_t beg,size_t end)
87 {
88 erase_impl(beg,end,typename std::iterator_traits<typename base::iterator>::iterator_category());
89 }
90 void set(size_t index,const T& t)
91 {
92 T* p = get(index);
93 if (p) *p = t;
94 }
95 T* get(size_t index)
96 {
97 return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
98 }
99 const T* get(size_t index) const
100 {
101 return get_impl(index,typename std::iterator_traits<typename base::iterator>::iterator_category());
102 }
103 T* front()
104 {
105 if (base::empty()) return NULL;
106 return &base::front();
107 }
108 const T* front() const
109 {
110 if (base::empty()) return NULL;
111 return &base::front();
112 }
113 T* back()
114 {
115 if (base::empty()) return NULL;
116 return &base::back();
117 }
118 const T* back() const
119 {
120 if (base::empty()) return NULL;
121 return &base::back();
122 }
123 bool is_empty() const
124 {
125 return base::empty();
126 }
127
128private:
129 /*************************************************************************************
130 下面函数仅作内部实现,需要注意以下几点
131 (1) 不让其子类和外部可见,故使用private访问控制
132 (2) 考虑到子类可能会使用using指令来引用,如果为重载形式,子类using引用同名函数
133 会因为private出错而不能引用public同名函数,故特命名为xxx_impl而非重载形式
134 *************************************************************************************/
135 void insert_impl(size_t index,const T& t,std::random_access_iterator_tag tag)
136 {
137 if (index < base::size())
138 {
139 base::insert(base::begin()+index,t);
140 }
141 }
142 void insert_impl(size_t index,const T& t,std::input_iterator_tag tag)
143 {
144 if (index < base::size())
145 {
146 typename base::iterator it = base::begin();
147 while(index--) ++it;
148 base::insert(it,t);
149 }
150 }
151 void erase_impl(size_t index,std::random_access_iterator_tag tag)
152 {
153 if (index < base::size())
154 {
155 base::erase(base::begin()+index);
156 }
157 }
158 void erase_impl(size_t index,std::input_iterator_tag tag)
159 {
160 if (index < base::size())
161 {
162 typename base::iterator it = base::begin();
163 while(index--) ++it;
164 base::erase(it);
165 }
166 }
167 void erase_impl(size_t beg,size_t end,std::random_access_iterator_tag tag)
168 {
169 end = std::min(end,base::size());
170 if (beg < end)
171 {
172 base::erase(base::begin()+beg,base::begin()+end);
173 }
174 }
175 void erase_impl(size_t beg,size_t end,std::input_iterator_tag tag)
176 {
177 end = std::min(end,base::size());
178 if (beg < end)
179 {
180 typename base::iterator it = base::begin();
181 while(beg++ < end) it = base::erase(it);
182 }
183 }
184 T* get_impl(size_t index,std::random_access_iterator_tag tag)
185 {
186 if (index>=base::size())
187 return NULL;
188 return &(*(base::begin()+index));
189 }
190 const T* get_impl(size_t index,std::random_access_iterator_tag tag) const
191 {
192 if (index>=base::size())
193 return NULL;
194 return &(*(base::begin()+index));
195 }
196 T* get_impl(size_t index,std::input_iterator_tag tag)
197 {
198 if (index>=base::size())
199 return NULL;
200 typename base::iterator it = base::begin();
201 while (index--) ++it;
202 return &(*it);
203 }
204 const T* get_impl(size_t index,std::input_iterator_tag tag) const
205 {
206 if (index>=base::size())
207 return NULL;
208 typename base::const_iterator it = base::begin();
209 while(index--) ++it;
210 return &(*it);
211 }
212} ;
213
214 #endif
1#ifndef _VARIANT_COLLECTION_H
2#define _VARIANT_COLLECTION_H
3
4#include <comutil.h>
5#pragma comment(lib,"comsuppw.lib")
6
7class variant_collection : public STLCollection<_variant_t>
8{
9 typedef STLCollection<_variant_t> base;
10
11public:
12 using base::add;
13 using base::insert;
14 using base::set;
15
16 void add(signed char val)
17 {
18 add<signed char>(val);
19 }
20 void add(unsigned char val)
21 {
22 add<unsigned char>(val);
23 }
24 void add(short val)
25 {
26 add<short>(val);
27 }
28 void add(unsigned short val)
29 {
30 add<unsigned short>(val);
31 }
32 void add(int val)
33 {
34 add<int>(val);
35 }
36 void add(unsigned int val)
37 {
38 add<unsigned int>(val);
39 }
40 void add(float val)
41 {
42 add<float>(val);
43 }
44 void add(double val)
45 {
46 add<double>(val);
47 }
48 void add(const char* val)
49 {
50 add<const char*>(val);
51 }
52
53 void insert(size_t index,signed char val)
54 {
55 insert<signed char>(index,val);
56 }
57 void insert(size_t index,unsigned char val)
58 {
59 insert<unsigned char>(index,val);
60 }
61 void insert(size_t index,short val)
62 {
63 insert<short>(index,val);
64 }
65 void insert(size_t index,unsigned short val)
66 {
67 insert<unsigned short>(index,val);
68 }
69 void insert(size_t index,int val)
70 {
71 insert<int>(index,val);
72 }
73 void insert(size_t index,unsigned int val)
74 {
75 insert<unsigned int>(index,val);
76 }
77 void insert(size_t index,float val)
78 {
79 insert<float>(index,val);
80 }
81 void insert(size_t index,double val)
82 {
83 insert<double>(index,val);
84 }
85 void insert(size_t index,const char* val)
86 {
87 insert<const char*>(index,val);
88 }
89
90 void set(size_t index,signed char val)
91 {
92 set<signed char>(index,val);
93 }
94 void set(size_t index,unsigned char val)
95 {
96 set<unsigned char>(index,val);
97 }
98 void set(size_t index,short val)
99 {
100 set<short>(index,val);
101 }
102 void set(size_t index,unsigned short val)
103 {
104 set<unsigned short>(index,val);
105 }
106 void set(size_t index,int val)
107 {
108 set<int>(index,val);
109 }
110 void set(size_t index,unsigned int val)
111 {
112 set<unsigned int>(index,val);
113 }
114 void set(size_t index,float val)
115 {
116 set<float>(index,val);
117 }
118 void set(size_t index,double val)
119 {
120 set<double>(index,val);
121 }
122 void set(size_t index,const char* val)
123 {
124 set<const char*>(index,val);
125 }
126
127protected:
128 template<typename T>
129 void add(T val)
130 {
131 _variant_t var(val);
132 base::add(var);
133 }
134 template<typename T>
135 void insert(size_t index,T val)
136 {
137 _variant_t var(val);
138 base::insert(index,var);
139 }
140 template<typename T>
141 void set(size_t index,T val)
142 {
143 _variant_t* p_var = base::get(index);
144 if (p_var) *p_var = val;
145 }
146};
147
148#endif