CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/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 "boost/functional.hpp"
00107 #include "boost/call_traits.hpp"
00108 #include "boost/type_traits.hpp"
00109 #include "boost/mpl/has_xxx.hpp"
00110 #include "boost/utility/enable_if.hpp"
00111 
00112 #include "DataFormats/Provenance/interface/ProductID.h"
00113 #include "DataFormats/Common/interface/EDProductGetter.h"
00114 #include "DataFormats/Common/interface/EDProductfwd.h"
00115 #include "DataFormats/Common/interface/RefBase.h"
00116 #include "DataFormats/Common/interface/traits.h"
00117 #include "DataFormats/Common/interface/Handle.h"
00118 #include "DataFormats/Common/interface/OrphanHandle.h"
00119 #include "DataFormats/Common/interface/TestHandle.h"
00120 
00121 BOOST_MPL_HAS_XXX_TRAIT_DEF(key_compare)
00122 
00123   template <typename C, typename K>
00124   typename boost::enable_if<has_key_compare<C>, bool>::type
00125   compare_key(K const& lhs, K const& rhs) {
00126     typedef typename C::key_compare comparison_functor;
00127     return comparison_functor()(lhs, rhs);
00128   }
00129 
00130   template <typename C, typename K>
00131   typename boost::disable_if<has_key_compare<C>, bool>::type
00132   compare_key(K const& lhs, K const& rhs) {
00133     return lhs < rhs;
00134   }
00135 
00136 #include "DataFormats/Common/interface/RefTraits.h"
00137 
00138 namespace edm {
00139   template<typename C, typename T, typename F>
00140   class RefVector;
00141 
00142   template<typename T>
00143   class RefToBaseVector;
00144 
00145   template <typename C, 
00146             typename T = typename refhelper::ValueTrait<C>::value, 
00147             typename F = typename refhelper::FindTrait<C, T>::value>
00148   class Ref {
00149   private:
00150     typedef refhelper::FindRefVectorUsingAdvance<RefVector<C, T, F> > VF;
00151     typedef refhelper::FindRefVectorUsingAdvance<RefToBaseVector<T> > VBF;
00152     friend class RefVectorIterator<C, T, F>;
00153     friend class RefVector<C, T, F>;
00154     friend class RefVector<RefVector<C, T, F>, T, VF>;
00155     friend class RefVector<RefVector<RefVector<C, T, F>, T, VF>, T, VF>;
00156     friend class RefVector<RefVector<C, T, F>, T, VBF>;
00157     friend class RefVector<RefVector<RefVector<C, T, F>, T, VBF>, T, VBF>;
00159 
00160   public:
00162     typedef C product_type;
00163     typedef T value_type; 
00164     typedef T const element_type; //used for generic programming
00165     typedef F finder_type;
00166     typedef typename boost::binary_traits<F>::second_argument_type argument_type;
00167     typedef typename boost::remove_cv<typename boost::remove_reference<argument_type>::type>::type key_type;   
00170 
00172     Ref() : ref_() {}
00173 
00175     Ref(Handle<C> const& handle, key_type itemKey, bool setNow=true);
00176 
00178     Ref(OrphanHandle<C> const& handle, key_type itemKey, bool setNow=true);
00179 
00181     //  Note. refvector[index] returns a Ref where index is the index into
00182     //  the RefVector. This index argument is the index into the COLLECTION,
00183     //  not the index into the RefVector.
00184     Ref(RefVector<C, T, F> const& refvector, key_type itemKey, bool setNow=true);
00185 
00187     //  An exception will be thrown if an attempt is made to persistify
00188     //  any object containing this Ref.  Also, in the future work will
00189     //  be done to throw an exception if an attempt is made to put any object
00190     //  containing this Ref into an event(or run or lumi).
00191     Ref(C const* product, key_type itemKey, bool setNow=true);
00192 
00194     //  An exception will be thrown if an attempt is made to persistify
00195     //  any object containing this Ref.  Also, in the future work will
00196     Ref(TestHandle<C> const& handle, key_type itemKey, bool setNow=true);
00197 
00201     Ref(ProductID const& productID, key_type itemKey, EDProductGetter const* prodGetter) :
00202       ref_(productID, 0, itemKey, 0, mustBeNonZero(prodGetter, "Ref", productID), false) {
00203     }
00204 
00206     //  It is an error (not diagnosable at compile- or run-time) to call
00207     //  this constructor with a pointer to a T unless the pointed-to T
00208     //  object is already in a collection of type C stored in the
00209     //  Event. The given ProductID must be the id of the collection in
00210     //  the Event.
00211     
00212     Ref(ProductID const& productID, T const* item, key_type item_key, C const* product ) :
00213       ref_(productID, product, item_key, item, 0, false) { 
00214     }
00215 
00219 
00220     explicit Ref(ProductID const& id) :
00221       ref_(id, 0, key_traits<key_type>::value, 0, 0, false)
00222     { }
00223 
00225     Ref(RefProd<C> const& refProd, key_type itemKey);
00226 
00228     ~Ref() {}
00229 
00231     T const&
00232     operator*() const;
00233 
00235     T const*
00236     operator->() const;
00237 
00239     T const* get() const {
00240       return isNull() ? 0 : this->operator->();
00241     }
00242 
00244     bool isNull() const {return !isNonnull(); }
00245 
00247     //bool isNonnull() const {return id().isValid(); }
00248     bool isNonnull() const { return ref_.isNonnull(); }
00249 
00251     bool operator!() const {return isNull();}
00252 
00254     ProductID id() const {return ref_.refCore().id();}
00255 
00257     EDProductGetter const* productGetter() const {return ref_.refCore().productGetter();}
00258 
00260     // Accessor must get the product if necessary
00261     C const* product() const;
00262 
00264     key_type key() const {return ref_.item().key();}
00265 
00266     // This one just for backward compatibility.  Will be removed soon.
00267     key_type index() const {return ref_.item().key();}
00268 
00270     RefBase<key_type> const& ref() const {return ref_;}
00271 
00272     bool hasProductCache() const {return ref_.refCore().productPtr() != 0;}
00273 
00274     bool hasCache() const {return ref_.item().ptr() != 0;}
00275 
00278     bool isAvailable() const {return ref_.refCore().isAvailable();}
00279 
00281     bool isTransient() const {return ref_.refCore().isTransient();}
00282 
00283   private:
00284     // Constructor from member of RefVector
00285     Ref(RefCore const& refCore, RefItem<key_type> const& item) : 
00286       ref_(refCore, item) {
00287       }
00288 
00289   private:
00290     // Compile time check that the argument is a C* or C const*
00291     // or derived from it.
00292     void checkTypeAtCompileTime(C const*) {}
00293 
00294     RefBase<key_type> ref_;
00295   };
00296 }
00297 
00298 #include "DataFormats/Common/interface/RefProd.h"
00299 #include "DataFormats/Common/interface/RefCoreGet.h"
00300 #include "DataFormats/Common/interface/RefItemGet.h"
00301 
00302 namespace edm {
00304   template <typename C, typename T, typename F>
00305   inline
00306   Ref<C, T, F>::Ref(Handle<C> const& handle, key_type itemKey, bool setNow) :
00307       ref_(handle.id(), handle.product(), itemKey, 0, 0, false) {
00308     checkTypeAtCompileTime(handle.product());
00309     assert(ref_.item().key() == itemKey);
00310         
00311     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00312   }
00313 
00315   template <typename C, typename T, typename F>
00316   inline
00317   Ref<C, T, F>::Ref(OrphanHandle<C> const& handle, key_type itemKey, bool setNow) :
00318       ref_(handle.id(), handle.product(), itemKey, 0, 0, false) {
00319     checkTypeAtCompileTime(handle.product());
00320     assert(ref_.item().key() == itemKey);
00321         
00322     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00323   }
00324 
00326   template <typename C, typename T, typename F>
00327   inline
00328   Ref<C, T, F>::Ref(RefVector<C, T, F> const& refvector, key_type itemKey, bool setNow) :
00329       ref_(refvector.id(), refvector.product(), itemKey, 0, 0, refvector.isTransient()) {
00330     checkTypeAtCompileTime(refvector.product());
00331     assert(ref_.item().key() == itemKey);
00332         
00333     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00334   }
00335 
00337   //  An exception will be thrown if an attempt is made to persistify
00338   //  any object containing this Ref.  Also, in the future work will
00339   //  be done to throw an exception if an attempt is made to put any object
00340   //  containing this Ref into an event(or run or lumi).
00341   //  Note:  It is legal for the referenced object to be put into the event
00342   //  and persistified.  It is this Ref itself that cannot be persistified.
00343   template <typename C, typename T, typename F>
00344   inline
00345   Ref<C, T, F>::Ref(C const* product, key_type itemKey, bool setNow) :
00346       ref_(ProductID(), product, product != 0 ? itemKey : key_traits<key_type>::value, 0, 0, true) {
00347     checkTypeAtCompileTime(product);
00348     assert(ref_.item().key() == (product != 0 ? itemKey : key_traits<key_type>::value));
00349         
00350     if (setNow && product != 0) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00351   }
00352 
00354   //  An exception will be thrown if an attempt is made to persistify any object containing this Ref.
00355   template <typename C, typename T, typename F>
00356   inline
00357   Ref<C, T, F>::Ref(TestHandle<C> const& handle, key_type itemKey, bool setNow) :
00358       ref_(handle.id(), handle.product(), itemKey, 0, 0, true) {
00359     checkTypeAtCompileTime(handle.product());
00360     assert(ref_.item().key() == itemKey);
00361         
00362     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00363   }
00364 
00366   template <typename C, typename T, typename F>
00367   inline
00368   Ref<C, T, F>::Ref(RefProd<C> const& refProd, key_type itemKey) :
00369       ref_(refProd.id(), refProd.refCore().productPtr(), itemKey, 0, refProd.refCore().productGetter(), refProd.refCore().isTransient()) {
00370     assert(ref_.item().key() == itemKey);
00371     if (0 != refProd.refCore().productPtr()) {
00372       ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));
00373     }
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>(ref_.refCore());
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>(ref_.refCore(), ref_.item());
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>(ref_.refCore(), ref_.item());
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.ref() == rhs.ref();
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.ref().refCore() == rhs.ref().refCore() ? compare_key<C>(lhs.key(), rhs.key()) : lhs.ref().refCore() < rhs.ref().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