CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/DataFormats/Common/interface/Ref.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_Ref_h
00002 #define DataFormats_Common_Ref_h
00003 
00004 /*----------------------------------------------------------------------
00005   
00006 Ref: A template for a interproduct reference to a member of a product_.
00007 
00008 ----------------------------------------------------------------------*/
00074 /*----------------------------------------------------------------------
00075 //  This defines the public interface to the class Ref<C, T, F>.
00076 //  C                         is the collection type.
00077 //  T (default C::value_type) is the type of an element in the collection.
00078 //
00079 //  ProductID productID       is the product ID of the collection.
00080 //  key_type itemKey          is the key of the element in the collection.
00081 //  C::value_type *itemPtr    is a C++ pointer to the element 
00082 //  Ref<C, T, F> const& ref   is another Ref<C, T, F>
00083 
00084 //  Constructors
00085     Ref(); // Default constructor
00086     Ref(Ref<C, T> const& ref);  // Copy constructor  (default, not explicitly specified)
00087 
00088     Ref(Handle<C> const& handle, key_type itemKey);
00089     Ref(ProductID pid, key_type itemKey, EDProductGetter const* prodGetter);
00090 
00091 //  Destructor
00092     virtual ~Ref() {}
00093 
00094     // Operators and methods
00095     Ref<C, T>& operator=(Ref<C, T> const&);             // assignment (default, not explicitly specified)
00096     T const& operator*() const;                 // dereference
00097     T const* const operator->() const;          // member dereference
00098     bool operator==(Ref<C, T> const& ref) const; // equality
00099     bool operator!=(Ref<C, T> const& ref) const; // inequality
00100     bool operator<(Ref<C, T> const& ref) const; // ordering
00101     bool isNonnull() const;                     // true if an object is referenced
00102     bool isNull() const;                        // equivalent to !isNonnull()
00103     bool operator!() const;                     // equivalent to !isNonnull()
00104     ----------------------------------------------------------------------*/ 
00105 
00106 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00107 #include "DataFormats/Common/interface/ConstPtrCache.h"
00108 #include "DataFormats/Common/interface/EDProductfwd.h"
00109 #include "DataFormats/Common/interface/EDProductGetter.h"
00110 #include "DataFormats/Common/interface/Handle.h"
00111 #include "DataFormats/Common/interface/OrphanHandle.h"
00112 #include "DataFormats/Common/interface/RefCore.h"
00113 #include "DataFormats/Common/interface/TestHandle.h"
00114 #include "DataFormats/Common/interface/traits.h"
00115 #include "DataFormats/Provenance/interface/ProductID.h"
00116 
00117 #include "boost/functional.hpp"
00118 #include "boost/call_traits.hpp"
00119 #include "boost/type_traits.hpp"
00120 #include "boost/mpl/has_xxx.hpp"
00121 #include "boost/utility/enable_if.hpp"
00122 
00123 BOOST_MPL_HAS_XXX_TRAIT_DEF(key_compare)
00124 
00125   template <typename C, typename K>
00126   typename boost::enable_if<has_key_compare<C>, bool>::type
00127   compare_key(K const& lhs, K const& rhs) {
00128     typedef typename C::key_compare comparison_functor;
00129     return comparison_functor()(lhs, rhs);
00130   }
00131 
00132   template <typename C, typename K>
00133   typename boost::disable_if<has_key_compare<C>, bool>::type
00134   compare_key(K const& lhs, K const& rhs) {
00135     return lhs < rhs;
00136   }
00137 
00138 #include "DataFormats/Common/interface/RefTraits.h"
00139 
00140 namespace edm {
00141   template<typename C, typename T, typename F>
00142   class RefVector;
00143 
00144   template<typename T>
00145   class RefToBaseVector;
00146 
00147   template <typename C, 
00148             typename T = typename refhelper::ValueTrait<C>::value, 
00149             typename F = typename refhelper::FindTrait<C, T>::value>
00150   class Ref {
00151   private:
00152     typedef refhelper::FindRefVectorUsingAdvance<RefVector<C, T, F> > VF;
00153     typedef refhelper::FindRefVectorUsingAdvance<RefToBaseVector<T> > VBF;
00154     friend class RefVectorIterator<C, T, F>;
00155     friend class RefVector<C, T, F>;
00156     friend class RefVector<RefVector<C, T, F>, T, VF>;
00157     friend class RefVector<RefVector<RefVector<C, T, F>, T, VF>, T, VF>;
00158     friend class RefVector<RefVector<C, T, F>, T, VBF>;
00159     friend class RefVector<RefVector<RefVector<C, T, F>, T, VBF>, T, VBF>;
00161 
00162   public:
00164     typedef C product_type;
00165     typedef T value_type; 
00166     typedef T const element_type; //used for generic programming
00167     typedef F finder_type;
00168     typedef typename boost::binary_traits<F>::second_argument_type argument_type;
00169     typedef typename boost::remove_cv<typename boost::remove_reference<argument_type>::type>::type key_type;   
00172 
00174     Ref() : product_(), index_(key_traits<key_type>::value) {}
00175 
00177     Ref(Handle<C> const& handle, key_type itemKey, bool setNow=true);
00178 
00180     Ref(OrphanHandle<C> const& handle, key_type itemKey, bool setNow=true);
00181 
00183     //  Note. refvector[index] returns a Ref where index is the index into
00184     //  the RefVector. This index argument is the index into the COLLECTION,
00185     //  not the index into the RefVector.
00186     Ref(RefVector<C, T, F> const& refvector, key_type itemKey, bool setNow=true);
00187 
00189     //  An exception will be thrown if an attempt is made to persistify
00190     //  any object containing this Ref.  Also, in the future work will
00191     //  be done to throw an exception if an attempt is made to put any object
00192     //  containing this Ref into an event(or run or lumi).
00193     Ref(C const* product, key_type itemKey, bool setNow=true);
00194 
00196     //  An exception will be thrown if an attempt is made to persistify
00197     //  any object containing this Ref.  Also, in the future work will
00198     Ref(TestHandle<C> const& handle, key_type itemKey, bool setNow=true);
00199 
00203     Ref(ProductID const& productID, key_type itemKey, EDProductGetter const* prodGetter) :
00204       product_(productID, 0, mustBeNonZero(prodGetter, "Ref", productID), false), index_(itemKey) {
00205     }
00206 
00208     //  It is an error (not diagnosable at compile- or run-time) to call
00209     //  this constructor with a pointer to a T unless the pointed-to T
00210     //  object is already in a collection of type C stored in the
00211     //  Event. The given ProductID must be the id of the collection in
00212     //  the Event.
00213     
00214     Ref(ProductID const& iProductID, T const* /*item*/, key_type iItemKey, C const* iProduct) :
00215       product_(iProductID, iProduct, 0, false), index_(iItemKey)
00216     { }
00217 
00221 
00222     explicit Ref(ProductID const& iId) :
00223       product_(iId, 0, 0, false), index_(key_traits<key_type>::value)
00224     { }
00225 
00227     Ref(RefProd<C> const& refProd, key_type itemKey);
00228 
00230     ~Ref() {}
00231 
00233     T const&
00234     operator*() const;
00235 
00237     T const*
00238     operator->() const;
00239 
00241     T const* get() const {
00242       return isNull() ? 0 : this->operator->();
00243     }
00244 
00246     bool isNull() const {return !isNonnull(); }
00247 
00249     bool isNonnull() const { return index_!=edm::key_traits<key_type>::value; }
00250 
00252     bool operator!() const {return isNull();}
00253 
00255     ProductID id() const {return product_.id();}
00256 
00258     EDProductGetter const* productGetter() const {return product_.productGetter();}
00259 
00261     // Accessor must get the product if necessary
00262     C const* product() const;
00263 
00265     key_type key() const {return index_;}
00266 
00267     // This one just for backward compatibility.  Will be removed soon.
00268     key_type index() const {return index_;}
00269 
00271     bool hasProductCache() const {return product_.productPtr() != 0;}
00272 
00275     bool isAvailable() const {return product_.isAvailable();}
00276 
00278     bool isTransient() const {return product_.isTransient();}
00279 
00280     RefCore const& refCore() const {return product_;}
00281     
00282     //Used by ROOT storage
00283     CMS_CLASS_VERSION(10)
00284     //  private:
00285     // Constructor from member of RefVector
00286     Ref(RefCore const& iRefCore, key_type const& iKey) : 
00287       product_(iRefCore), index_(iKey) {
00288     }
00289 
00290   private:
00291     // Compile time check that the argument is a C* or C const*
00292     // or derived from it.
00293     void checkTypeAtCompileTime(C const*) {}
00294 
00295     mutable RefCore product_;
00296     key_type index_;
00297 
00298   };
00299 }
00300 
00301 #include "DataFormats/Common/interface/RefProd.h"
00302 #include "DataFormats/Common/interface/RefCoreGet.h"
00303 #include "DataFormats/Common/interface/RefItemGet.h"
00304 
00305 namespace edm {
00307   template <typename C, typename T, typename F>
00308   inline
00309   Ref<C, T, F>::Ref(Handle<C> const& handle, key_type itemKey, bool setNow) :
00310       product_(handle.id(), handle.product(), 0, false), index_(itemKey){
00311     checkTypeAtCompileTime(handle.product());
00312     assert(key() == itemKey);
00313         
00314     if (setNow) {getPtr_<C, T, F>(product_, index_);}
00315   }
00316 
00318   template <typename C, typename T, typename F>
00319   inline
00320   Ref<C, T, F>::Ref(OrphanHandle<C> const& handle, key_type itemKey, bool setNow) :
00321   product_(handle.id(), handle.product(), 0, false), index_(itemKey) {
00322     checkTypeAtCompileTime(handle.product());
00323     assert(key() == itemKey);
00324         
00325     if (setNow) {getPtr_<C, T, F>(product_, index_);}
00326   }
00327 
00329   template <typename C, typename T, typename F>
00330   inline
00331   Ref<C, T, F>::Ref(RefVector<C, T, F> const& refvector, key_type itemKey, bool setNow) :
00332       product_(refvector.id(), refvector.product(), 0, refvector.isTransient()), index_(itemKey) {
00333     checkTypeAtCompileTime(refvector.product());
00334     assert(key() == itemKey);
00335         
00336     if (setNow) {getPtr_<C, T, F>(product_, index_);}
00337   }
00338 
00340   //  An exception will be thrown if an attempt is made to persistify
00341   //  any object containing this Ref.  Also, in the future work will
00342   //  be done to throw an exception if an attempt is made to put any object
00343   //  containing this Ref into an event(or run or lumi).
00344   //  Note:  It is legal for the referenced object to be put into the event
00345   //  and persistified.  It is this Ref itself that cannot be persistified.
00346   template <typename C, typename T, typename F>
00347   inline
00348   Ref<C, T, F>::Ref(C const* iProduct, key_type iItemKey, bool iSetNow) :
00349     product_(ProductID(), iProduct, 0, true), index_(iProduct != 0 ? iItemKey : key_traits<key_type>::value) {
00350     checkTypeAtCompileTime(iProduct);
00351     assert(key() == (iProduct != 0 ? iItemKey : key_traits<key_type>::value));
00352         
00353     if (iSetNow && iProduct != 0) {getPtr_<C, T, F>(product_, index_);}
00354   }
00355 
00357   //  An exception will be thrown if an attempt is made to persistify any object containing this Ref.
00358   template <typename C, typename T, typename F>
00359   inline
00360   Ref<C, T, F>::Ref(TestHandle<C> const& handle, key_type itemKey, bool setNow) :
00361       product_(handle.id(), handle.product(), 0, true), index_(itemKey) {
00362     checkTypeAtCompileTime(handle.product());
00363     assert(key() == itemKey);
00364         
00365     if (setNow) {getPtr_<C, T, F>(product_, index_);}
00366   }
00367 
00369   template <typename C, typename T, typename F>
00370   inline
00371   Ref<C, T, F>::Ref(RefProd<C> const& refProd, key_type itemKey) :
00372       product_(refProd.id(), refProd.refCore().productPtr(), refProd.refCore().productGetter(), refProd.refCore().isTransient()), index_(itemKey) {
00373     assert(index() == itemKey);
00374   }
00375 
00377   // Accessor must get the product if necessary
00378   template <typename C, typename T, typename F>
00379   inline
00380   C const*
00381   Ref<C, T, F>::product() const {
00382       return isNull() ? 0 : edm::template getProduct<C>(product_);
00383   }
00384 
00386   template <typename C, typename T, typename F>
00387   inline
00388   T const&
00389   Ref<C, T, F>::operator*() const {
00390     return *getPtr<C, T, F>(product_, index_);
00391   }
00392 
00394   template <typename C, typename T, typename F>
00395   inline
00396   T const*
00397   Ref<C, T, F>::operator->() const {
00398     return getPtr<C, T, F>(product_, index_);
00399   }
00400 
00401   template <typename C, typename T, typename F>
00402   inline
00403   bool
00404   operator==(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00405     return lhs.key() == rhs.key() && lhs.refCore() == rhs.refCore() ;
00406   }
00407 
00408   template <typename C, typename T, typename F>
00409   inline
00410   bool
00411   operator!=(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00412     return !(lhs == rhs);
00413   }
00414 
00415   template <typename C, typename T, typename F>
00416   inline
00417   bool
00418   operator<(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00421       return (lhs.refCore() == rhs.refCore() ? compare_key<C>(lhs.key(), rhs.key()) : lhs.refCore() < rhs.refCore());
00422   }
00423 
00424 }
00425 
00426 #include "DataFormats/Common/interface/HolderToVectorTrait.h"
00427 #include "DataFormats/Common/interface/Holder.h"
00428 #include "DataFormats/Common/interface/VectorHolder.h"
00429 #include "DataFormats/Common/interface/RefVector.h"
00430 
00431 namespace edm {
00432   namespace reftobase {
00433 
00434     template <typename T, typename REF>
00435     struct RefHolderToVector {
00436       static  std::auto_ptr<BaseVectorHolder<T> > makeVectorHolder() {
00437         typedef RefVector<typename REF::product_type,
00438                           typename REF::value_type, 
00439                           typename REF::finder_type> REFV;
00440         return std::auto_ptr<BaseVectorHolder<T> >(new VectorHolder<T, REFV>);
00441       }
00442       static  std::auto_ptr<RefVectorHolderBase> makeVectorBaseHolder() {
00443         typedef RefVector<typename REF::product_type,
00444                           typename REF::value_type, 
00445                           typename REF::finder_type> REFV;
00446         return std::auto_ptr<RefVectorHolderBase>(new RefVectorHolder<REFV>);
00447       }
00448     };
00449 
00450     template<typename T1, typename C, typename T, typename F>
00451     struct HolderToVectorTrait<T1, Ref<C, T, F> > {
00452       typedef RefHolderToVector<T1, Ref<C, T, F> > type;
00453     };
00454 
00455     template <typename REF>
00456     struct RefRefHolderToRefVector {
00457       static std::auto_ptr<RefVectorHolderBase> makeVectorHolder() {
00458         typedef RefVector<typename REF::product_type,
00459                           typename REF::value_type, 
00460                                 typename REF::finder_type> REFV;
00461         return std::auto_ptr<RefVectorHolderBase>(new RefVectorHolder<REFV>);
00462       }
00463     };
00464 
00465     template<typename C, typename T, typename F>
00466     struct RefHolderToRefVectorTrait<Ref<C, T, F> > {
00467       typedef RefRefHolderToRefVector<Ref<C, T, F> > type;
00468     };
00469 
00470   }
00471 }
00472   
00473 #endif