CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/DataFormats/Common/interface/RefToBase.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_RefToBase_h
00002 #define DataFormats_Common_RefToBase_h
00003 // -*- C++ -*-
00004 //
00005 // Package:     Common
00006 // Class  :     RefToBase
00007 //
00028 //
00029 // Original Author:  Chris Jones
00030 //         Created:  Mon Apr  3 16:37:59 EDT 2006
00031 //
00032 
00033 // system include files
00034 
00035 // user include files
00036 
00037 #include "boost/shared_ptr.hpp"
00038 #include "boost/static_assert.hpp"
00039 #include "boost/type_traits/is_base_of.hpp"
00040 
00041 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00042 #include "DataFormats/Common/interface/EDProductfwd.h"
00043 #include "FWCore/Utilities/interface/EDMException.h"
00044 #include "DataFormats/Common/interface/BaseHolder.h"
00045 
00046 #include "DataFormats/Common/interface/Holder.h"
00047 #include "DataFormats/Common/interface/IndirectHolder.h"
00048 #include "DataFormats/Common/interface/RefHolder.h"
00049 
00050 namespace edm {
00051   //--------------------------------------------------------------------
00052   // Class template RefToBase<T>
00053   //--------------------------------------------------------------------
00054 
00058 
00059   template<typename T> class RefToBaseVector;
00060   template<typename C, typename T, typename F> class Ref;
00061   template<typename C> class RefProd;
00062   template<typename T> class RefToBaseProd;
00063   template<typename T> class View;
00064 
00065   template <class T>
00066   class RefToBase
00067   {
00068   public:
00069     typedef T   value_type;
00070 
00071     RefToBase();
00072     RefToBase(RefToBase const& other);
00073     template <typename C1, typename T1, typename F1>
00074     explicit RefToBase(Ref<C1, T1, F1> const& r);
00075     template <typename C>
00076     explicit RefToBase(RefProd<C> const& r);
00077     RefToBase(RefToBaseProd<T> const& r, size_t i);
00078     RefToBase(Handle<View<T> > const& handle, size_t i);
00079     template <typename T1>
00080     explicit RefToBase(RefToBase<T1> const & r );
00081     RefToBase(boost::shared_ptr<reftobase::RefHolderBase> p);
00082     ~RefToBase();
00083 
00084     RefToBase& operator= (RefToBase const& rhs);
00085 
00086     value_type const& operator*() const;
00087     value_type const* operator->() const;
00088     value_type const* get() const;
00089 
00090     ProductID id() const;
00091     size_t key() const;
00092 
00093     template <class REF> REF castTo() const;
00094 
00095     bool isNull() const;
00096     bool isNonnull() const;
00097     bool operator!() const;
00098 
00099     bool operator==(RefToBase const& rhs) const;
00100     bool operator!=(RefToBase const& rhs) const;
00101 
00102     void swap(RefToBase& other);
00103 
00104     std::auto_ptr<reftobase::RefHolderBase> holder() const;
00105 
00106     EDProductGetter const* productGetter() const;
00107     bool hasProductCache() const;
00108     void const * product() const;
00109 
00112     bool isAvailable() const { return holder_->isAvailable(); }
00113     
00114     //Needed for ROOT storage
00115     CMS_CLASS_VERSION(10)
00116   private:
00117     value_type const* getPtrImpl() const;
00118     reftobase::BaseHolder<value_type>* holder_;
00119     friend class RefToBaseVector<T>;
00120     friend class RefToBaseProd<T>;
00121     template<typename B> friend class RefToBase;
00122   };
00123 
00124   //--------------------------------------------------------------------
00125   // Implementation of RefToBase<T>
00126   //--------------------------------------------------------------------
00127 
00128   template <class T>
00129   inline
00130   RefToBase<T>::RefToBase() :
00131     holder_(0)
00132   { }
00133 
00134   template <class T>
00135   inline
00136   RefToBase<T>::RefToBase(RefToBase const& other) :
00137     holder_(other.holder_  ? other.holder_->clone() : 0)
00138   { }
00139 
00140   template <class T>
00141   template <typename C1, typename T1, typename F1>
00142   inline
00143   RefToBase<T>::RefToBase(Ref<C1, T1, F1> const& iRef) :
00144     holder_(new reftobase::Holder<T,Ref<C1, T1, F1> >(iRef))
00145   { }
00146 
00147   template <class T>
00148   template <typename C>
00149   inline
00150   RefToBase<T>::RefToBase(RefProd<C> const& iRef) :
00151     holder_(new reftobase::Holder<T,RefProd<C> >(iRef))
00152   { }
00153 
00154   template <class T>
00155   template <typename T1>
00156   inline
00157   RefToBase<T>::RefToBase(RefToBase<T1> const& iRef) :
00158         holder_(new reftobase::IndirectHolder<T> (
00159              boost::shared_ptr< edm::reftobase::RefHolderBase>(iRef.holder().release())
00160         ) )
00161   {
00162     // OUT: holder_( new reftobase::Holder<T,RefToBase<T1> >(iRef ) )  {
00163     // Forcing the conversion through IndirectHolder,
00164     //   as Holder<T,RefToBase<T1>> would need dictionaries we will never have.
00165     // In this way we only need the IndirectHolder<T> and the RefHolder of the real type of the item
00166     // This might cause a small performance penalty.
00167     BOOST_STATIC_ASSERT( ( boost::is_base_of<T, T1>::value ) );
00168   }
00169 
00170   template <class T>
00171   inline
00172   RefToBase<T>::RefToBase(boost::shared_ptr<reftobase::RefHolderBase> p) :
00173     holder_(new reftobase::IndirectHolder<T>(p))
00174   { }
00175 
00176   template <class T>
00177   inline
00178   RefToBase<T>::~RefToBase()
00179   {
00180     delete holder_;
00181   }
00182 
00183   template <class T>
00184   inline
00185   RefToBase<T>&
00186   RefToBase<T>:: operator= (RefToBase<T> const& iRHS)
00187   {
00188     RefToBase<T> temp( iRHS);
00189     temp.swap(*this);
00190     return *this;
00191   }
00192 
00193   template <class T>
00194   inline
00195   T const&
00196   RefToBase<T>::operator*() const
00197   {
00198     return *getPtrImpl();
00199   }
00200 
00201   template <class T>
00202   inline
00203   T const*
00204   RefToBase<T>::operator->() const
00205   {
00206     return getPtrImpl();
00207   }
00208 
00209   template <class T>
00210   inline
00211   T const*
00212   RefToBase<T>::get() const
00213   {
00214     return getPtrImpl();
00215   }
00216 
00217   template <class T>
00218   inline
00219   ProductID
00220   RefToBase<T>::id() const
00221   {
00222     return  holder_ ? holder_->id() : ProductID();
00223   }
00224 
00225   template <class T>
00226   inline
00227   size_t
00228   RefToBase<T>::key() const
00229   {
00230     if ( holder_ == 0 )
00231         Exception::throwThis(errors::InvalidReference,
00232           "attempting get key from  null RefToBase;\n"
00233           "You should check for nullity before calling key().");
00234     return  holder_->key();
00235   }
00236 
00238   template <class T>
00239   template <class REF>
00240   REF
00241   RefToBase<T>::castTo() const
00242   {
00243     if (!holder_)
00244       {
00245         Exception::throwThis(errors::InvalidReference,
00246           "attempting to cast a null RefToBase;\n"
00247           "You should check for nullity before casting.");
00248       }
00249 
00250     reftobase::RefHolder<REF> concrete_holder;
00251     std::string hidden_ref_type;
00252     if (!holder_->fillRefIfMyTypeMatches(concrete_holder,
00253                                          hidden_ref_type))
00254       {
00255         Exception::throwThis(errors::InvalidReference,
00256           "cast to type: ",
00257           typeid(REF).name(),
00258           "\nfrom type: ",
00259           hidden_ref_type.c_str(),
00260           " failed. Catch this exception in case you need to check"
00261           " the concrete reference type.");
00262       }
00263     return concrete_holder.getRef();
00264   }
00265 
00267   template <class T>
00268   inline
00269   bool
00270   RefToBase<T>::isNull() const
00271   {
00272     return !id().isValid();
00273   }
00274 
00276   template <class T>
00277   inline
00278   bool
00279   RefToBase<T>::isNonnull() const
00280   {
00281     return !isNull();
00282   }
00283 
00285   template <class T>
00286   inline
00287   bool
00288   RefToBase<T>::operator!() const
00289   {
00290     return isNull();
00291   }
00292 
00293   template <class T>
00294   inline
00295   bool
00296   RefToBase<T>::operator==(RefToBase<T> const& rhs) const
00297   {
00298     return holder_
00299       ? holder_->isEqualTo(*rhs.holder_)
00300       : holder_ == rhs.holder_;
00301   }
00302 
00303   template <class T>
00304   inline
00305   bool
00306   RefToBase<T>::operator!=(RefToBase<T> const& rhs) const
00307   {
00308     return !(*this == rhs);
00309   }
00310 
00311   template <class T>
00312   inline
00313   void
00314   RefToBase<T>::swap(RefToBase<T> & other)
00315   {
00316     std::swap(holder_, other.holder_);
00317   }
00318 
00319   template <class T>
00320   inline
00321   EDProductGetter const* RefToBase<T>::productGetter() const {
00322     return holder_->productGetter();
00323   }
00324 
00325   template <class T>
00326   inline
00327   bool RefToBase<T>::hasProductCache() const {
00328     return holder_->hasProductCache();
00329   }
00330 
00331   template <class T>
00332   inline
00333   void const * RefToBase<T>::product() const {
00334     return holder_->product();
00335   }
00336 
00337   template <class T>
00338   inline
00339   T const*
00340   RefToBase<T>::getPtrImpl() const
00341   {
00342     return holder_ ? holder_->getPtr() : 0;
00343   }
00344 
00345   template <class T>
00346   std::auto_ptr<reftobase::RefHolderBase> RefToBase<T>::holder() const {
00347     return holder_->holder();
00348   }
00349 
00350   // Free swap function
00351   template <class T>
00352   inline
00353   void
00354   swap(RefToBase<T>& a, RefToBase<T>& b)
00355   {
00356     a.swap(b);
00357   }
00358 }
00359 
00360 #include "DataFormats/Common/interface/RefToBaseProd.h"
00361 #include "DataFormats/Common/interface/Handle.h"
00362 #include "DataFormats/Common/interface/View.h"
00363 
00364 namespace edm {
00365   template <class T>
00366   inline
00367   RefToBase<T>::RefToBase(RefToBaseProd<T> const& r, size_t i) :
00368     holder_( r.operator->()->refAt( i ).holder_->clone() ) {
00369   }
00370 
00371   template<typename T>
00372   inline
00373   RefToBase<T>::RefToBase(Handle<View<T> > const& handle, size_t i) :
00374     holder_( handle.operator->()->refAt( i ).holder_->clone() ) {
00375   }
00376 
00377 }
00378 
00379 #endif