CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:30:15 2009 for CMSSW by  doxygen 1.5.4