CMS 3D CMS Logo

OwnVector.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_OwnVector_h
00002 #define DataFormats_Common_OwnVector_h
00003 // $Id: OwnVector.h,v 1.37 2009/02/12 19:43:01 wmtan Exp $
00004 
00005 #include <algorithm>
00006 #include <functional>
00007 #include <vector>
00008 
00009 #include "DataFormats/Common/interface/EDProduct.h"
00010 #include "DataFormats/Common/interface/ClonePolicy.h"
00011 #include "DataFormats/Common/interface/traits.h"
00012 #include "DataFormats/Common/interface/Ref.h"
00013 #include "DataFormats/Common/interface/RefToBase.h"
00014 
00015 #include "DataFormats/Provenance/interface/ProductID.h"
00016 
00017 #include "FWCore/Utilities/interface/EDMException.h"
00018 
00019 #if defined CMS_USE_DEBUGGING_ALLOCATOR
00020 #include "DataFormats/Common/interface/debugging_allocator.h"
00021 #endif
00022 
00023 #include "DataFormats/Common/interface/PostReadFixupTrait.h"
00024 
00025 namespace edm {
00026   template <typename T, typename P = ClonePolicy<T> >
00027   class OwnVector  {
00028   private:
00029 #if defined(CMS_USE_DEBUGGING_ALLOCATOR)
00030     typedef std::vector<T*, debugging_allocator<T> > base;
00031 #else
00032     typedef std::vector<T*> base;
00033 #endif
00034 
00035   public:
00036     typedef typename base::size_type size_type;
00037     typedef T value_type;
00038     typedef T* pointer;
00039     typedef T& reference;
00040     typedef T const& const_reference;
00041     typedef P policy_type;
00042       
00043     class iterator;
00044     class const_iterator {
00045     public:
00046       typedef T value_type;
00047       typedef T* pointer;
00048       typedef T const& reference; 
00049       typedef ptrdiff_t difference_type;
00050       typedef typename base::const_iterator::iterator_category iterator_category;
00051       const_iterator(typename base::const_iterator const& it) : i(it) { }
00052       const_iterator(const_iterator const& it) : i(it.i) { }
00053       const_iterator(iterator const& it) : i(it.i) { }
00054       const_iterator() {}
00055       const_iterator& operator=(const_iterator const& it) { i = it.i; return *this; }
00056       const_iterator& operator++() { ++i; return *this; }
00057       const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; }
00058       const_iterator& operator--() { --i; return *this; }
00059       const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; }
00060       difference_type operator-(const_iterator const& o) const { return i - o.i; }
00061       const_iterator operator+(difference_type n) const { return const_iterator(i + n); }
00062       const_iterator operator-(difference_type n) const { return const_iterator(i - n); }
00063       bool operator<(const_iterator const& o) const { return i < o.i; }
00064       bool operator==(const_iterator const& ci) const { return i == ci.i; }
00065       bool operator!=(const_iterator const& ci) const { return i != ci.i; }
00066       T const& operator *() const { return **i; }
00067       //    operator T const*() const { return & **i; }
00068       T const* operator->() const { return & (operator*()); }
00069       const_iterator & operator +=(difference_type d) { i += d; return *this; }
00070       const_iterator & operator -=(difference_type d) { i -= d; return *this; }
00071       reference operator[](difference_type d) const { return *const_iterator(i+d); } // for boost::iterator_range []
00072     private:
00073       typename base::const_iterator i;
00074     };
00075     class iterator {
00076     public:
00077       typedef T value_type;
00078       typedef T * pointer;
00079       typedef T & reference;
00080       typedef ptrdiff_t difference_type;
00081       typedef typename base::iterator::iterator_category iterator_category;
00082       iterator(typename base::iterator const& it) : i(it) { }
00083       iterator(iterator const& it) : i(it.i) { }
00084       iterator() {}
00085       iterator & operator=(iterator const& it) { i = it.i; return *this; }
00086       iterator& operator++() { ++i; return *this; }
00087       iterator operator++(int) { iterator ci = *this; ++i; return ci; }
00088       iterator& operator--() { --i; return *this; }
00089       iterator operator--(int) { iterator ci = *this; --i; return ci; }
00090       difference_type operator-(iterator const& o) const { return i - o.i; }
00091       iterator operator+(difference_type n) const { return iterator(i + n); }
00092       iterator operator-(difference_type n) const { return iterator(i - n); }
00093       bool operator<(iterator const& o) const { return i < o.i; }
00094       bool operator==(iterator const& ci) const { return i == ci.i; }
00095       bool operator!=(iterator const& ci) const { return i != ci.i; }
00096       T & operator *() const { return **i; }
00097       //    operator T *() const { return & **i; }
00098       //T *& get() { return *i; }
00099       T * operator->() const { return & (operator*()); }
00100       iterator & operator +=(difference_type d) { i += d; return *this; }
00101       iterator & operator -=(difference_type d) { i -= d; return *this; }
00102       reference operator[](difference_type d) const { return *iterator(i+d); } // for boost::iterator_range []
00103     private:
00104       typename base::iterator i;
00105       friend const_iterator::const_iterator(iterator const&);
00106       friend class OwnVector<T, P>;
00107    };
00108       
00109     OwnVector();
00110     OwnVector(size_type);
00111     OwnVector(OwnVector const&);
00112     ~OwnVector();
00113       
00114     iterator begin();
00115     iterator end();
00116     const_iterator begin() const;
00117     const_iterator end() const;
00118     size_type size() const;
00119     bool empty() const;
00120     reference operator[](size_type);
00121     const_reference operator[](size_type) const;
00122       
00123     OwnVector<T, P> & operator=(OwnVector<T, P> const&);
00124       
00125     void reserve(size_t);
00126     template <typename D> void push_back(D*& d);
00127     template <typename D> void push_back(D* const& d);
00128     template <typename D> void push_back(std::auto_ptr<D> d);
00129     void push_back(T const& valueToCopy);
00130     bool is_back_safe() const;
00131     void pop_back();
00132     reference back();
00133     const_reference back() const;
00134     reference front();
00135     const_reference front() const;
00136     base const& data() const; 
00137     void clear();
00138     iterator erase(iterator pos);
00139     iterator erase(iterator first, iterator last);
00140     template<typename S> 
00141     void sort(S s);
00142     void sort();
00143 
00144     void swap(OwnVector<T, P> & other);
00145 
00146     void fillView(ProductID const& id,
00147                   std::vector<void const*>& pointers,
00148                   helper_vector& helpers) const;
00149 
00150   private:
00151     void destroy();
00152     template<typename O>
00153     struct Ordering {
00154       Ordering(O const& c) : comp(c) { }
00155       bool operator()(T const* t1, T const* t2) const {
00156         return comp(*t1, *t2);
00157       }
00158     private:
00159       O comp;
00160     };
00161     template<typename O>
00162     static Ordering<O> ordering(O const& comp) {
00163       return Ordering<O>(comp);
00164     }
00165     base data_;      
00166     typename helpers::PostReadFixupTrait<T>::type fixup_;
00167     inline void fixup() const { fixup_(data_); }
00168     inline void touch() { fixup_.touch(); }
00169   };
00170   
00171   template<typename T, typename P>
00172   inline OwnVector<T, P>::OwnVector() : data_() { 
00173   }
00174   
00175   template<typename T, typename P>
00176   inline OwnVector<T, P>::OwnVector(size_type n) : data_(n) { 
00177   }
00178   
00179   template<typename T, typename P>
00180   inline OwnVector<T, P>::OwnVector(OwnVector<T, P> const& o) : data_(o.size()) {
00181     size_type current = 0;
00182     for (const_iterator i = o.begin(), e = o.end(); i != e; ++i,++current) 
00183       data_[current] = policy_type::clone(*i);
00184   }
00185   
00186   template<typename T, typename P>
00187   inline OwnVector<T, P>::~OwnVector() { 
00188     destroy();
00189   }
00190   
00191   template<typename T, typename P>
00192   inline OwnVector<T, P> & OwnVector<T, P>::operator=(OwnVector<T, P> const& o) {
00193     OwnVector<T,P> temp(o);
00194     swap(temp);
00195     fixup_ = o.fixup_;
00196     return *this;
00197   }
00198   
00199   template<typename T, typename P>
00200   inline typename OwnVector<T, P>::iterator OwnVector<T, P>::begin() {
00201     fixup();
00202     touch();
00203     return iterator(data_.begin());
00204   }
00205   
00206   template<typename T, typename P>
00207   inline typename OwnVector<T, P>::iterator OwnVector<T, P>::end() {
00208     fixup();
00209     touch();
00210     return iterator(data_.end());
00211   }
00212   
00213   template<typename T, typename P>
00214   inline typename OwnVector<T, P>::const_iterator OwnVector<T, P>::begin() const {
00215     fixup();
00216     return const_iterator(data_.begin());
00217   }
00218   
00219   template<typename T, typename P>
00220   inline typename OwnVector<T, P>::const_iterator OwnVector<T, P>::end() const {
00221     fixup();
00222     return const_iterator(data_.end());
00223   }
00224   
00225   template<typename T, typename P>
00226   inline typename OwnVector<T, P>::size_type OwnVector<T, P>::size() const {
00227     return data_.size();
00228   }
00229   
00230   template<typename T, typename P>
00231   inline bool OwnVector<T, P>::empty() const {
00232     return data_.empty();
00233   }
00234   
00235   template<typename T, typename P>
00236   inline typename OwnVector<T, P>::reference OwnVector<T, P>::operator[](size_type n) {
00237     fixup();
00238     return *data_[n];
00239   }
00240   
00241   template<typename T, typename P>
00242   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::operator[](size_type n) const {
00243     fixup();
00244     return *data_[n];
00245   }
00246   
00247   template<typename T, typename P>
00248   inline void OwnVector<T, P>::reserve(size_t n) {
00249     data_.reserve(n);
00250   }
00251   
00252   template<typename T, typename P>
00253   template<typename D>
00254   inline void OwnVector<T, P>::push_back(D*& d) {
00255     // C++ does not yet support rvalue references, so d should only be
00256     // able to bind to an lvalue.
00257     // This should be called only for lvalues.
00258     data_.push_back(d);
00259     d = 0;
00260     touch();
00261   }
00262 
00263   template<typename T, typename P>
00264   template<typename D>
00265   inline void OwnVector<T, P>::push_back(D* const& d) {
00266 
00267     // C++ allows d to be bound to an lvalue or rvalue. But the other
00268     // signature should be a better match for an lvalue (because it
00269     // does not require an lvalue->rvalue conversion). Thus this
00270     // signature should only be chosen for rvalues.
00271     data_.push_back(d);
00272     touch();
00273   }
00274 
00275 
00276   template<typename T, typename P>
00277   template<typename D>
00278   inline void OwnVector<T, P>::push_back(std::auto_ptr<D> d) {
00279     data_.push_back(d.release());
00280     touch();
00281   }
00282 
00283 
00284   template<typename T, typename P>
00285   inline void OwnVector<T, P>::push_back(T const& d) {
00286     data_.push_back(policy_type::clone(d));
00287     touch();
00288   }
00289 
00290 
00291   template<typename T, typename P>
00292   inline void OwnVector<T, P>::pop_back() {
00293     // We have to delete the pointed-to thing, before we squeeze it
00294     // out of the vector...
00295     delete data_.back();
00296     data_.pop_back();
00297     touch();
00298   }
00299 
00300   template <typename T, typename P>
00301   inline bool OwnVector<T, P>::is_back_safe() const {
00302     return data_.back() != 0;
00303   }
00304 
00305   template<typename T, typename P>
00306   inline typename OwnVector<T, P>::reference OwnVector<T, P>::back() {
00307     T* result = data_.back();
00308     if (result == 0)
00309       throw edm::Exception(errors::NullPointerError)
00310         << "In OwnVector::back() we have intercepted an attempt to dereference a null pointer\n"
00311         << "Since OwnVector is allowed to contain null pointers, you much assure that the\n"
00312         << "pointer at the end of the collection is not null before calling back()\n"
00313         << "if you wish to avoid this exception.\n"
00314         << "Consider using OwnVector::is_back_safe()\n";
00315     fixup();
00316     touch();
00317     return *data_.back();
00318   }
00319   
00320   template<typename T, typename P>
00321   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::back() const {
00322     T* result = data_.back();
00323     if (result == 0)
00324       throw edm::Exception(errors::NullPointerError)
00325         << "In OwnVector::back() we have intercepted an attempt to dereference a null pointer\n"
00326         << "Since OwnVector is allowed to contain null pointers, you much assure that the\n"
00327         << "pointer at the end of the collection is not null before calling back()\n"
00328         << "if you wish to avoid this exception.\n"
00329         << "Consider using OwnVector::is_back_safe()\n";
00330     fixup();
00331     return *data_.back();
00332   }
00333   
00334   template<typename T, typename P>
00335   inline typename OwnVector<T, P>::reference OwnVector<T, P>::front() {
00336     fixup();
00337     touch();
00338     return *data_.front();
00339   }
00340   
00341   template<typename T, typename P>
00342   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::front() const {
00343     fixup();
00344     return *data_.front();
00345   }
00346   
00347   template<typename T, typename P>
00348   inline void OwnVector<T, P>::destroy() {
00349     typename base::const_iterator b = data_.begin(), e = data_.end();
00350     for( typename base::const_iterator i = b; i != e; ++ i )
00351       delete * i;
00352   }
00353   
00354   template<typename T, typename P>
00355   inline typename OwnVector<T, P>::base const& OwnVector<T, P>::data() const {
00356     fixup();
00357     return data_;
00358   }
00359 
00360   template<typename T, typename P>
00361   inline void OwnVector<T, P>::clear() {
00362     destroy();
00363     data_.clear();
00364   }
00365 
00366   template<typename T, typename P>
00367   typename OwnVector<T, P>::iterator OwnVector<T, P>::erase(iterator pos) {
00368     fixup();
00369     touch();
00370     delete * pos.i;
00371     return iterator(data_.erase(pos.i));
00372   }
00373 
00374   template<typename T, typename P>
00375   typename OwnVector<T, P>::iterator OwnVector<T, P>::erase(iterator first, iterator last) {
00376     fixup();
00377     touch();
00378     typename base::iterator b = first.i, e = last.i;
00379     for( typename base::iterator i = b; i != e; ++ i )
00380       delete * i;    
00381     return iterator(data_.erase(b, e));
00382   }
00383 
00384   template<typename T, typename P> template<typename S>
00385   void OwnVector<T, P>::sort(S comp) {
00386     std::sort(data_.begin(), data_.end(), ordering(comp));
00387   }
00388 
00389   template<typename T, typename P>
00390   void OwnVector<T, P>::sort() {
00391     std::sort(data_.begin(), data_.end(), ordering(std::less<value_type>()));
00392   }
00393 
00394   template<typename T, typename P>
00395   inline void OwnVector<T, P>::swap(OwnVector<T, P>& other) {
00396     data_.swap(other.data_);
00397     std::swap(fixup_, other.fixup_);
00398   }
00399 
00400   template<typename T, typename P>
00401   void OwnVector<T, P>::fillView(ProductID const& id,
00402                                  std::vector<void const*>& pointers,
00403                                  helper_vector& helpers) const
00404   {
00405     typedef Ref<OwnVector>      ref_type ;
00406     typedef reftobase::RefHolder<ref_type> holder_type;
00407 
00408     size_type numElements = this->size();
00409     pointers.reserve(numElements);
00410     helpers.reserve(numElements);
00411     size_type key = 0;
00412     for(typename base::const_iterator i=data_.begin(), e=data_.end(); i!=e; ++i, ++key) {
00413 
00414       if (*i == 0) {
00415         throw edm::Exception(errors::NullPointerError)
00416           << "In OwnVector::fillView() we have intercepted an attempt to put a null pointer\n"
00417           << "into a View and that is not allowed.  It is probably an error that the null\n"
00418           << "pointer was in the OwnVector in the first place.\n";
00419       }
00420       else {
00421         pointers.push_back(*i);
00422         holder_type h(ref_type(id, *i, key,this));
00423         helpers.push_back(&h);
00424       }
00425     }
00426   }
00427 
00428   template<typename T, typename P>
00429   inline void swap(OwnVector<T, P>& a, OwnVector<T, P>& b) {
00430     a.swap(b);
00431   }
00432 
00433   //----------------------------------------------------------------------
00434   //
00435   // Free function template to support creation of Views.
00436 
00437   template <typename T, typename P>
00438   inline
00439   void
00440   fillView(OwnVector<T,P> const& obj,
00441            ProductID const& id,
00442            std::vector<void const*>& pointers,
00443            helper_vector& helpers) {
00444     obj.fillView(id, pointers, helpers);
00445   }
00446 
00447   template <typename T, typename P>
00448   struct has_fillView<edm::OwnVector<T, P> >
00449   {
00450     static bool const value = true;
00451   };
00452 
00453 }
00454 
00455 #endif

Generated on Tue Jun 9 17:29:36 2009 for CMSSW by  doxygen 1.5.4