CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/DataFormats/Common/interface/OwnVector.h

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