CMS 3D CMS Logo

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