CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/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 "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00005 #include "DataFormats/Common/interface/ClonePolicy.h"
00006 #include "DataFormats/Common/interface/fillPtrVector.h"
00007 #include "DataFormats/Common/interface/PostReadFixupTrait.h"
00008 #include "DataFormats/Common/interface/Ref.h"
00009 #include "DataFormats/Common/interface/setPtr.h"
00010 #include "DataFormats/Common/interface/traits.h"
00011 
00012 #if defined CMS_USE_DEBUGGING_ALLOCATOR
00013 #include "DataFormats/Common/interface/debugging_allocator.h"
00014 #endif
00015 #include "FWCore/Utilities/interface/EDMException.h"
00016 
00017 #include <algorithm>
00018 #include <functional>
00019 #include <typeinfo>
00020 #include <vector>
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(std::type_info const& toType,
00162                        std::vector<unsigned long> const& indices,
00163                        std::vector<void const*>& ptrs) const;
00164 
00165 
00166     //Used by ROOT storage
00167     CMS_CLASS_VERSION(10)
00168 
00169   private:
00170     void destroy();
00171     template<typename O>
00172     struct Ordering {
00173       Ordering(O const& c) : comp(c) { }
00174       bool operator()(T const* t1, T const* t2) const {
00175         return comp(*t1, *t2);
00176       }
00177     private:
00178       O comp;
00179     };
00180     template<typename O>
00181     static Ordering<O> ordering(O const& comp) {
00182       return Ordering<O>(comp);
00183     }
00184     base data_;
00185     typename helpers::PostReadFixupTrait<T>::type fixup_;
00186     inline void fixup() const { fixup_(data_); }
00187     inline void touch() { fixup_.touch(); }
00188   };
00189 
00190   template<typename T, typename P>
00191   inline OwnVector<T, P>::OwnVector() : data_() {
00192   }
00193 
00194   template<typename T, typename P>
00195   inline OwnVector<T, P>::OwnVector(size_type n) : data_(n) {
00196   }
00197 
00198   template<typename T, typename P>
00199   inline OwnVector<T, P>::OwnVector(OwnVector<T, P> const& o) : data_(o.size()) {
00200     size_type current = 0;
00201     for (const_iterator i = o.begin(), e = o.end(); i != e; ++i,++current)
00202       data_[current] = policy_type::clone(*i);
00203     fixup_ = o.fixup_;
00204   }
00205 
00206 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00207   template<typename T, typename P>
00208   inline OwnVector<T, P>::OwnVector(OwnVector<T, P>&& o)  {
00209     data_.swap(o.data_);
00210     fixup_ = o.fixup_;
00211   }
00212 #endif
00213 
00214   template<typename T, typename P>
00215   inline OwnVector<T, P>::~OwnVector() {
00216     destroy();
00217   }
00218 
00219   template<typename T, typename P>
00220   inline OwnVector<T, P>& OwnVector<T, P>::operator=(OwnVector<T, P> const& o) {
00221     OwnVector<T,P> temp(o);
00222     swap(temp);
00223     return *this;
00224   }
00225 
00226 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00227   template<typename T, typename P>
00228   inline OwnVector<T, P>& OwnVector<T, P>::operator=(OwnVector<T, P>&& o) {
00229     data_.swap(o.data_);
00230     fixup_ = o.fixup_;
00231     return *this;
00232   }
00233 #endif
00234 
00235 
00236   template<typename T, typename P>
00237   inline typename OwnVector<T, P>::iterator OwnVector<T, P>::begin() {
00238     fixup();
00239     touch();
00240     return iterator(data_.begin());
00241   }
00242 
00243   template<typename T, typename P>
00244   inline typename OwnVector<T, P>::iterator OwnVector<T, P>::end() {
00245     fixup();
00246     touch();
00247     return iterator(data_.end());
00248   }
00249 
00250   template<typename T, typename P>
00251   inline typename OwnVector<T, P>::const_iterator OwnVector<T, P>::begin() const {
00252     fixup();
00253     return const_iterator(data_.begin());
00254   }
00255 
00256   template<typename T, typename P>
00257   inline typename OwnVector<T, P>::const_iterator OwnVector<T, P>::end() const {
00258     fixup();
00259     return const_iterator(data_.end());
00260   }
00261 
00262   template<typename T, typename P>
00263   inline typename OwnVector<T, P>::size_type OwnVector<T, P>::size() const {
00264     return data_.size();
00265   }
00266 
00267   template<typename T, typename P>
00268   inline bool OwnVector<T, P>::empty() const {
00269     return data_.empty();
00270   }
00271 
00272   template<typename T, typename P>
00273   inline typename OwnVector<T, P>::reference OwnVector<T, P>::operator[](size_type n) {
00274     fixup();
00275     return *data_[n];
00276   }
00277 
00278   template<typename T, typename P>
00279   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::operator[](size_type n) const {
00280     fixup();
00281     return *data_[n];
00282   }
00283 
00284   template<typename T, typename P>
00285   inline void OwnVector<T, P>::reserve(size_t n) {
00286     data_.reserve(n);
00287   }
00288 
00289   template<typename T, typename P>
00290   template<typename D>
00291   inline void OwnVector<T, P>::push_back(D*& d) {
00292     // C++ does not yet support rvalue references, so d should only be
00293     // able to bind to an lvalue.
00294     // This should be called only for lvalues.
00295     data_.push_back(d);
00296     d = 0;
00297     touch();
00298   }
00299 
00300   template<typename T, typename P>
00301   template<typename D>
00302   inline void OwnVector<T, P>::push_back(D* const& d) {
00303 
00304     // C++ allows d to be bound to an lvalue or rvalue. But the other
00305     // signature should be a better match for an lvalue (because it
00306     // does not require an lvalue->rvalue conversion). Thus this
00307     // signature should only be chosen for rvalues.
00308     data_.push_back(d);
00309     touch();
00310   }
00311 
00312 
00313   template<typename T, typename P>
00314   template<typename D>
00315   inline void OwnVector<T, P>::push_back(std::auto_ptr<D> d) {
00316     data_.push_back(d.release());
00317     touch();
00318   }
00319 
00320 
00321   template<typename T, typename P>
00322   inline void OwnVector<T, P>::push_back(T const& d) {
00323     data_.push_back(policy_type::clone(d));
00324     touch();
00325   }
00326 
00327 
00328   template<typename T, typename P>
00329   inline void OwnVector<T, P>::pop_back() {
00330     // We have to delete the pointed-to thing, before we squeeze it
00331     // out of the vector...
00332     delete data_.back();
00333     data_.pop_back();
00334     touch();
00335   }
00336 
00337   template <typename T, typename P>
00338   inline bool OwnVector<T, P>::is_back_safe() const {
00339     return data_.back() != 0;
00340   }
00341 
00342   template<typename T, typename P>
00343   inline typename OwnVector<T, P>::reference OwnVector<T, P>::back() {
00344     T* result = data_.back();
00345     if (result == 0) {
00346       Exception::throwThis(errors::NullPointerError,
00347         "In OwnVector::back() we have intercepted an attempt to dereference a null pointer\n"
00348         "Since OwnVector is allowed to contain null pointers, you much assure that the\n"
00349         "pointer at the end of the collection is not null before calling back()\n"
00350         "if you wish to avoid this exception.\n"
00351         "Consider using OwnVector::is_back_safe()\n");
00352     }
00353     fixup();
00354     touch();
00355     return *data_.back();
00356   }
00357 
00358   template<typename T, typename P>
00359   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::back() const {
00360     T* result = data_.back();
00361     if (result == 0) {
00362       Exception::throwThis(errors::NullPointerError,
00363         "In OwnVector::back() we have intercepted an attempt to dereference a null pointer\n"
00364         "Since OwnVector is allowed to contain null pointers, you much assure that the\n"
00365         "pointer at the end of the collection is not null before calling back()\n"
00366         "if you wish to avoid this exception.\n"
00367         "Consider using OwnVector::is_back_safe()\n");
00368     }
00369     fixup();
00370     return *data_.back();
00371   }
00372 
00373   template<typename T, typename P>
00374   inline typename OwnVector<T, P>::reference OwnVector<T, P>::front() {
00375     fixup();
00376     touch();
00377     return *data_.front();
00378   }
00379 
00380   template<typename T, typename P>
00381   inline typename OwnVector<T, P>::const_reference OwnVector<T, P>::front() const {
00382     fixup();
00383     return *data_.front();
00384   }
00385 
00386   template<typename T, typename P>
00387   inline void OwnVector<T, P>::destroy() {
00388     typename base::const_iterator b = data_.begin(), e = data_.end();
00389     for(typename base::const_iterator i = b; i != e; ++ i)
00390       delete * i;
00391   }
00392 
00393   template<typename T, typename P>
00394   inline typename OwnVector<T, P>::base const& OwnVector<T, P>::data() const {
00395     fixup();
00396     return data_;
00397   }
00398 
00399   template<typename T, typename P>
00400   inline void OwnVector<T, P>::clear() {
00401     destroy();
00402     data_.clear();
00403   }
00404 
00405   template<typename T, typename P>
00406   typename OwnVector<T, P>::iterator OwnVector<T, P>::erase(iterator pos) {
00407     fixup();
00408     touch();
00409     delete * pos.i;
00410     return iterator(data_.erase(pos.i));
00411   }
00412 
00413   template<typename T, typename P>
00414   typename OwnVector<T, P>::iterator OwnVector<T, P>::erase(iterator first, iterator last) {
00415     fixup();
00416     touch();
00417     typename base::iterator b = first.i, e = last.i;
00418     for(typename base::iterator i = b; i != e; ++ i)
00419       delete * i;
00420     return iterator(data_.erase(b, e));
00421   }
00422 
00423   template<typename T, typename P> template<typename S>
00424   void OwnVector<T, P>::sort(S comp) {
00425     std::sort(data_.begin(), data_.end(), ordering(comp));
00426   }
00427 
00428   template<typename T, typename P>
00429   void OwnVector<T, P>::sort() {
00430     std::sort(data_.begin(), data_.end(), ordering(std::less<value_type>()));
00431   }
00432 
00433   template<typename T, typename P>
00434   inline void OwnVector<T, P>::swap(OwnVector<T, P>& other) {
00435     data_.swap(other.data_);
00436     std::swap(fixup_, other.fixup_);
00437   }
00438 
00439   template<typename T, typename P>
00440   void OwnVector<T, P>::fillView(ProductID const& id,
00441                                  std::vector<void const*>& pointers,
00442                                  helper_vector& helpers) const {
00443     typedef Ref<OwnVector>      ref_type ;
00444     typedef reftobase::RefHolder<ref_type> holder_type;
00445 
00446     size_type numElements = this->size();
00447     pointers.reserve(numElements);
00448     helpers.reserve(numElements);
00449     size_type key = 0;
00450     for(typename base::const_iterator i=data_.begin(), e=data_.end(); i!=e; ++i, ++key) {
00451 
00452       if (*i == 0) {
00453         Exception::throwThis(errors::NullPointerError,
00454           "In OwnVector::fillView() we have intercepted an attempt to put a null pointer\n"
00455           "into a View and that is not allowed.  It is probably an error that the null\n"
00456           "pointer was in the OwnVector in the first place.\n");
00457       }
00458       else {
00459         pointers.push_back(*i);
00460         holder_type h(ref_type(id, *i, key,this));
00461         helpers.push_back(&h);
00462       }
00463     }
00464   }
00465 
00466   template<typename T, typename P>
00467   inline void swap(OwnVector<T, P>& a, OwnVector<T, P>& b) {
00468     a.swap(b);
00469   }
00470 
00471   //----------------------------------------------------------------------
00472   //
00473   // Free function template to support creation of Views.
00474 
00475   template <typename T, typename P>
00476   inline
00477   void
00478   fillView(OwnVector<T,P> const& obj,
00479            ProductID const& id,
00480            std::vector<void const*>& pointers,
00481            helper_vector& helpers) {
00482     obj.fillView(id, pointers, helpers);
00483   }
00484 
00485 
00486   template <typename T, typename P>
00487   struct has_fillView<edm::OwnVector<T, P> > {
00488     static bool const value = true;
00489   };
00490 
00491 
00492   // Free function templates to support the use of edm::Ptr.
00493 
00494   template <typename T, typename P>
00495   inline
00496   void
00497   OwnVector<T,P>::setPtr(std::type_info const& toType,
00498                                    unsigned long index,
00499                                    void const*& ptr) const {
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     obj.setPtr(toType, index, ptr);
00511   }
00512 
00513   template <typename T, typename P>
00514   inline
00515   void
00516     OwnVector<T,P>::fillPtrVector(std::type_info const& toType,
00517                                   std::vector<unsigned long> const& indices,
00518                                   std::vector<void const*>& ptrs) const {
00519     detail::reallyfillPtrVector(*this, toType, indices, ptrs);
00520   }
00521 
00522 
00523   template <typename T, typename P>
00524   inline
00525   void
00526   fillPtrVector(OwnVector<T,P> const& obj,
00527                 std::type_info const& toType,
00528                 std::vector<unsigned long> const& indices,
00529                 std::vector<void const*>& ptrs) {
00530     obj.fillPtrVector(toType, indices, ptrs);
00531   }
00532 
00533 
00534   template <typename T, typename P>
00535    struct has_setPtr<edm::OwnVector<T,P> > {
00536      static bool const value = true;
00537    };
00538 
00539 
00540 }
00541 
00542 
00543 #endif