CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Common/interface/RefVectorHolder.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_RefVectorHolder_h
00002 #define DataFormats_Common_RefVectorHolder_h
00003 
00004 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00005 #include "DataFormats/Common/interface/RefVectorHolderBase.h"
00006 #include "FWCore/Utilities/interface/EDMException.h"
00007 #include "DataFormats/Provenance/interface/ProductID.h"
00008 
00009 namespace edm {
00010   namespace reftobase {
00011     class RefHolderBase;
00012     template <typename REF> class RefHolder;
00013 
00014     template<typename REFV>
00015     class RefVectorHolder : public RefVectorHolderBase  {
00016     public:
00017       RefVectorHolder() : RefVectorHolderBase() {
00018       }
00019       RefVectorHolder(REFV const& refs) : RefVectorHolderBase(), refs_(refs) {
00020       }
00021       explicit RefVectorHolder(ProductID const& iId) : RefVectorHolderBase(), refs_(iId) {
00022       }
00023       virtual ~RefVectorHolder() { }
00024       void swap(RefVectorHolder& other);
00025       RefVectorHolder& operator=(RefVectorHolder const& rhs);
00026       virtual bool empty() const;
00027       virtual size_type size() const;
00028       virtual void clear();
00029       virtual void push_back(RefHolderBase const* r);
00030       virtual void reserve(size_type n);
00031       virtual ProductID id() const;
00032       virtual EDProductGetter const* productGetter() const;
00033       virtual RefVectorHolder<REFV> * clone() const;
00034       virtual RefVectorHolder<REFV> * cloneEmpty() const;
00035       void setRefs(REFV const& refs);
00036       virtual void reallyFillView(void const*, ProductID const&, std::vector<void const*> &);
00037       virtual size_t keyForIndex(size_t idx) const;
00038 
00039       //Needed for ROOT storage
00040       CMS_CLASS_VERSION(10)
00041 
00042     private:
00043       typedef typename RefVectorHolderBase::const_iterator_imp const_iterator_imp;
00044 
00045     public:
00046       struct const_iterator_imp_specific : public const_iterator_imp {
00047         typedef ptrdiff_t difference_type;
00048         const_iterator_imp_specific() { }
00049         explicit const_iterator_imp_specific(typename REFV::const_iterator const& it) : i (it) { }
00050         ~const_iterator_imp_specific() { }
00051         const_iterator_imp_specific * clone() const { return new const_iterator_imp_specific(i); }
00052         void increase() { ++i; }
00053         void decrease() { --i; }
00054         void increase(difference_type d) { i += d; }
00055         void decrease(difference_type d) { i -= d; }
00056         bool equal_to(const_iterator_imp const* o) const { return i == dc(o); }
00057         bool less_than(const_iterator_imp const* o) const { return i < dc(o); }
00058         void assign(const_iterator_imp const* o) { i = dc(o); }
00059         boost::shared_ptr<RefHolderBase> deref() const;
00060         difference_type difference(const_iterator_imp const* o) const { return i - dc(o); }
00061       private:
00062         typename REFV::const_iterator const& dc(const_iterator_imp const* o) const {
00063           if (o == 0) {
00064             Exception::throwThis(errors::InvalidReference,
00065               "In RefVectorHolder trying to dereference a null pointer\n");
00066           }
00067           const_iterator_imp_specific const* oo = dynamic_cast<const_iterator_imp_specific const*>(o);
00068           if (oo == 0) {
00069             Exception::throwThis(errors::InvalidReference,
00070               "In RefVectorHolder trying to cast iterator to wrong type\n");
00071           }
00072           return oo->i;
00073         }
00074         typename REFV::const_iterator i;
00075       };
00076 
00077       typedef typename RefVectorHolderBase::const_iterator const_iterator;
00078 
00079       const_iterator begin() const {
00080         return const_iterator(new const_iterator_imp_specific(refs_.begin()));
00081       }
00082       const_iterator end() const {
00083         return const_iterator(new const_iterator_imp_specific(refs_.end()));
00084       }
00085       virtual void const* product() const {
00086         return refs_.product();
00087       }
00088 
00091       virtual bool isAvailable() const { return refs_.isAvailable(); }
00092 
00093     private:
00094       virtual boost::shared_ptr<reftobase::RefHolderBase> refBase(size_t idx) const;
00095       REFV refs_;
00096     };
00097 
00098     //
00099     // implementations for RefVectorHolder<REFV>
00100     //
00101 
00102     template <typename REFV>
00103     inline
00104     void RefVectorHolder<REFV>::swap(RefVectorHolder<REFV>& other) {
00105       this->RefVectorHolderBase::swap(other);
00106       refs_.swap(other.refs_);
00107     }
00108 
00109     template <typename REFV>
00110     inline
00111     RefVectorHolder<REFV>& RefVectorHolder<REFV>::operator=(RefVectorHolder<REFV> const& rhs) {
00112       RefVectorHolder<REFV> temp(rhs);
00113       this->swap(temp);
00114       return *this;
00115     }
00116 
00117     template<typename REFV>
00118     inline
00119     bool RefVectorHolder<REFV>::empty() const {
00120       return refs_.empty();
00121     }
00122 
00123     template<typename REFV>
00124     inline
00125     typename RefVectorHolder<REFV>::size_type RefVectorHolder<REFV>::size() const {
00126       return refs_.size();
00127     }
00128 
00129     template<typename REFV>
00130     inline
00131     void RefVectorHolder<REFV>::clear() {
00132       return refs_.clear();
00133     }
00134 
00135     template<typename REFV>
00136     inline
00137     void RefVectorHolder<REFV>::reserve(size_type n) {
00138       typename REFV::size_type s = n;
00139       refs_.reserve(s);
00140     }
00141 
00142     template<typename REFV>
00143     inline
00144     ProductID RefVectorHolder<REFV>::id() const {
00145       return refs_.id();
00146     }
00147 
00148     template<typename REFV>
00149     inline
00150     EDProductGetter const* RefVectorHolder<REFV>::productGetter() const {
00151       return refs_.productGetter();
00152     }
00153 
00154     template<typename REFV>
00155     inline
00156     RefVectorHolder<REFV> * RefVectorHolder<REFV>::clone() const {
00157       return new RefVectorHolder<REFV>(*this);
00158     }
00159 
00160     template<typename REFV>
00161     inline
00162     RefVectorHolder<REFV> * RefVectorHolder<REFV>::cloneEmpty() const {
00163       return new RefVectorHolder<REFV>(id());
00164     }
00165 
00166     template<typename REFV>
00167     inline
00168     void RefVectorHolder<REFV>::setRefs(REFV const& refs) {
00169       refs_ = refs;
00170     }
00171 
00172      template <typename REFV>
00173      inline
00174      size_t RefVectorHolder<REFV>::keyForIndex(size_t idx) const {
00175         return refs_[idx].key();
00176      }
00177      
00178      // Free swap function
00179     template <typename REFV>
00180     inline
00181     void
00182     swap(RefVectorHolder<REFV>& lhs, RefVectorHolder<REFV>& rhs) {
00183       lhs.swap(rhs);
00184     }
00185   }
00186 }
00187 
00188 #include "DataFormats/Common/interface/RefHolder.h"
00189 
00190 namespace edm {
00191   namespace reftobase {
00192 
00193     template<typename REFV>
00194     void RefVectorHolder<REFV>::push_back(RefHolderBase const* h) {
00195       typedef typename REFV::value_type REF;
00196       RefHolder<REF> const* rh = dynamic_cast<RefHolder<REF> const*>(h);
00197       if(rh == 0) {
00198         Exception::throwThis(errors::InvalidReference,
00199           "RefVectorHolder: attempting to cast a RefHolderBase "
00200           "to an invalid type.\nExpected: ",
00201           typeid(REF).name(),
00202           "\n");
00203       }
00204       refs_.push_back(rh->getRef());
00205     }
00206 
00207     template <typename REFV>
00208     boost::shared_ptr<RefHolderBase>
00209     RefVectorHolder<REFV>::refBase(size_t idx) const {
00210       return boost::shared_ptr<RefHolderBase>(new RefHolder<typename REFV::value_type>(refs_[idx]));
00211     }
00212 
00213     template<typename REFV>
00214     boost::shared_ptr<RefHolderBase> RefVectorHolder<REFV>::const_iterator_imp_specific::deref() const {
00215       return boost::shared_ptr<RefHolderBase>(new RefHolder<typename REFV::value_type>(*i));
00216     }
00217 
00218   }
00219 }
00220 
00221 #include "DataFormats/Common/interface/FillView.h"
00222 #include "DataFormats/Common/interface/traits.h"
00223 #include "boost/mpl/if.hpp"
00224 
00225 namespace edm {
00226   namespace reftobase {
00227     template<typename REFV>
00228     struct RefVectorHolderNoFillView {
00229       static void reallyFillView(RefVectorHolder<REFV>&, void const*, ProductID const&, std::vector<void const*>&) {
00230         Exception::throwThis(errors::ProductDoesNotSupportViews,
00231           "The product type ",
00232           typeid(typename REFV::collection_type).name(),
00233           "\ndoes not support Views\n");
00234       }
00235     };
00236 
00237     template<typename REFV>
00238     struct RefVectorHolderDoFillView {
00239       static void reallyFillView(RefVectorHolder<REFV>& rvh, void const* prod, ProductID const& id , std::vector<void const*> & pointers) {
00240         typedef typename REFV::collection_type collection;
00241         collection const* product = static_cast<collection const*>(prod);
00242         detail::reallyFillView(*product, id, pointers, rvh);
00243       }
00244     };
00245 
00246     template<typename REFV>
00247     void RefVectorHolder<REFV>::reallyFillView(void const* iProd, ProductID const& iId , std::vector<void const*> & oPointers) {
00248       typedef
00249         typename boost::mpl::if_c<has_fillView<typename REFV::collection_type>::value,
00250         RefVectorHolderDoFillView<REFV>,
00251         RefVectorHolderNoFillView<REFV> >::type maybe_filler;
00252       maybe_filler::reallyFillView(*this, iProd, iId, oPointers);
00253     }
00254   }
00255 }
00256 
00257 #endif