随笔-156  评论-223  文章-30  trackbacks-0
   在面向对象开发时,对实际问题分析进而抽象出一种类型,往往会考虑到2个方面:1)类型的内部成员和方法的定义描述 2)类型的多实例存取操作。其中第1点是类型本身数据结构的设计,第2点是类型容器数据结构的选择设计。在stl中,容器有序列式和关联式两种,前者代表有vector,list,deque等;后者代表有set,multiset,map,multimap等,对于一个类型的第2点,我们会考虑甚至是反复权衡选择序列容器还是关联容器?在确定选择了一种之后,比如序列式容器,又会进一步的思考是选择vetor、list、还是deque?实质上对它们的选择主要取决于应用的需要,比如要求快速访问就选择vetor,要求快速插入删除就选择list,符合队列模型就选择deque。如果对性能要求较高,就得选择关联式容器,这样访问、插入、删除元素都能得到较好的性能。如果操作太频繁,这时set,map还不行,要选择hash_set,hash_map等。
   本文仅探讨序列式容器的选择应用,对一个类型而言,既选择了序列式容器,就意味在vector,list,deque间选择(这里要说明的是,stack和queue虽然也是序列式容器,但从真正严格意义上讲,它们只是一种适配器)那么有没有办法作一个通用的包装类提供给开发者,让开发者自己根据应用决定选择具体的容器类型呢?同时这个包装又不影响原容器的接口使用。关于包装类的实现,代码描述如下
  1#ifndef _STL_COLLECTION_H
  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*/

 20template<typename T,template<class T,class U > class C = std::vector,template <class T> class U = std::allocator>
 21class 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) *= 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
   这样一来,由于STLCollection类提供了通用的操作接口,在应用时如果想切换改变为另一种容器,只需改变第2个模板参数即可,其它部分代码都不用改变,大大方便了程序的维护扩展,还可以继承STLCollection类,实现自己特殊的集合类,比如元素类型是_variant_t类型,代码描述如下

  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

posted on 2011-07-16 12:23 春秋十二月 阅读(1875) 评论(0)  编辑 收藏 引用 所属分类: Opensrc

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理