CMS 3D CMS Logo

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 $Id: Ref.h,v 1.38 2008/05/29 21:13:15 wmtan Exp $
00009 
00010 ----------------------------------------------------------------------*/
00076 /*----------------------------------------------------------------------
00077 //  This defines the public interface to the class Ref<C, T, F>.
00078 //  C                         is the collection type.
00079 //  T (default C::value_type) is the type of an element in the collection.
00080 //
00081 //  ProductID productID       is the product ID of the collection.
00082 //  key_type itemKey          is the key of the element in the collection.
00083 //  C::value_type *itemPtr    is a C++ pointer to the element 
00084 //  Ref<C, T, F> const& ref   is another Ref<C, T, F>
00085 
00086 //  Constructors
00087     Ref(); // Default constructor
00088     Ref(Ref<C, T> const& ref);  // Copy constructor  (default, not explicitly specified)
00089 
00090     Ref(Handle<C> const& handle, key_type itemKey);
00091     Ref(ProductID pid, key_type itemKey, EDProductGetter const* prodGetter);
00092 
00093 //  Destructor
00094     virtual ~Ref() {}
00095 
00096     // Operators and methods
00097     Ref<C, T>& operator=(Ref<C, T> const&);             // assignment (default, not explicitly specified)
00098     T const& operator*() const;                 // dereference
00099     T const* const operator->() const;          // member dereference
00100     bool operator==(Ref<C, T> const& ref) const; // equality
00101     bool operator!=(Ref<C, T> const& ref) const; // inequality
00102     bool operator<(Ref<C, T> const& ref) const; // ordering
00103     bool isNonnull() const;                     // true if an object is referenced
00104     bool isNull() const;                        // equivalent to !isNonnull()
00105     bool operator!() const;                     // equivalent to !isNonnull()
00106     ----------------------------------------------------------------------*/ 
00107 
00108 #include "boost/functional.hpp"
00109 #include "boost/call_traits.hpp"
00110 #include "boost/type_traits.hpp"
00111 #include "boost/mpl/has_xxx.hpp"
00112 #include "boost/utility/enable_if.hpp"
00113 
00114 #include "DataFormats/Provenance/interface/ProductID.h"
00115 #include "DataFormats/Common/interface/EDProductGetter.h"
00116 #include "DataFormats/Common/interface/EDProductfwd.h"
00117 #include "DataFormats/Common/interface/RefBase.h"
00118 #include "DataFormats/Common/interface/traits.h"
00119 #include "DataFormats/Common/interface/Handle.h"
00120 #include "DataFormats/Common/interface/OrphanHandle.h"
00121 #include "DataFormats/Common/interface/TestHandle.h"
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() : ref_() {}
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       ref_(productID, 0, itemKey, 0, mustBeNonZero(prodGetter, "Ref", productID), false) {
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& productID, T const* item, key_type item_key, C const* product ) :
00215       ref_(productID, product, item_key, item, 0, false) { 
00216     }
00217 
00221 
00222     explicit Ref(ProductID const& id) :
00223       ref_(id, 0, key_traits<key_type>::value, 0, 0, false)
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 id().isValid(); }
00250     bool isNonnull() const { return ref_.isNonnull(); }
00251 
00253     bool operator!() const {return isNull();}
00254 
00256     ProductID id() const {return ref_.refCore().id();}
00257 
00259     EDProductGetter const* productGetter() const {return ref_.refCore().productGetter();}
00260 
00262     // Accessor must get the product if necessary
00263     C const* product() const;
00264 
00266     key_type key() const {return ref_.item().key();}
00267 
00268     // This one just for backward compatibility.  Will be removed soon.
00269     key_type index() const {return ref_.item().key();}
00270 
00272     RefBase<key_type> const& ref() const {return ref_;}
00273 
00274     bool hasProductCache() const {return ref_.refCore().productPtr() != 0;}
00275 
00276     bool hasCache() const {return ref_.item().ptr() != 0;}
00277 
00280     bool isAvailable() const {return ref_.refCore().isAvailable();}
00281 
00283     bool isTransient() const {return ref_.refCore().isTransient();}
00284 
00285   private:
00286     // Constructor from member of RefVector
00287     Ref(RefCore const& refCore, RefItem<key_type> const& item) : 
00288       ref_(refCore, item) {
00289       }
00290 
00291   private:
00292     // Compile time check that the argument is a C* or C const*
00293     // or derived from it.
00294     void checkTypeAtCompileTime(C const* ptr) {}
00295 
00296     RefBase<key_type> ref_;
00297   };
00298 }
00299 
00300 #include "DataFormats/Common/interface/RefProd.h"
00301 #include "DataFormats/Common/interface/RefCoreGet.h"
00302 #include "DataFormats/Common/interface/RefItemGet.h"
00303 
00304 namespace edm {
00306   template <typename C, typename T, typename F>
00307   inline
00308   Ref<C, T, F>::Ref(Handle<C> const& handle, key_type itemKey, bool setNow) :
00309       ref_(handle.id(), handle.product(), itemKey, 0, 0, false) {
00310     checkTypeAtCompileTime(handle.product());
00311     assert(ref_.item().key() == itemKey);
00312         
00313     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00314   }
00315 
00317   template <typename C, typename T, typename F>
00318   inline
00319   Ref<C, T, F>::Ref(OrphanHandle<C> const& handle, key_type itemKey, bool setNow) :
00320       ref_(handle.id(), handle.product(), itemKey, 0, 0, false) {
00321     checkTypeAtCompileTime(handle.product());
00322     assert(ref_.item().key() == itemKey);
00323         
00324     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00325   }
00326 
00328   template <typename C, typename T, typename F>
00329   inline
00330   Ref<C, T, F>::Ref(RefVector<C, T, F> const& refvector, key_type itemKey, bool setNow) :
00331       ref_(refvector.id(), refvector.product(), itemKey, 0, 0, refvector.isTransient()) {
00332     checkTypeAtCompileTime(refvector.product());
00333     assert(ref_.item().key() == itemKey);
00334         
00335     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00336   }
00337 
00339   //  An exception will be thrown if an attempt is made to persistify
00340   //  any object containing this Ref.  Also, in the future work will
00341   //  be done to throw an exception if an attempt is made to put any object
00342   //  containing this Ref into an event(or run or lumi).
00343   //  Note:  It is legal for the referenced object to be put into the event
00344   //  and persistified.  It is this Ref itself that cannot be persistified.
00345   template <typename C, typename T, typename F>
00346   inline
00347   Ref<C, T, F>::Ref(C const* product, key_type itemKey, bool setNow) :
00348       ref_(ProductID(), product, product != 0 ? itemKey : key_traits<key_type>::value, 0, 0, true) {
00349     checkTypeAtCompileTime(product);
00350     assert(ref_.item().key() == (product != 0 ? itemKey : key_traits<key_type>::value));
00351         
00352     if (setNow && product != 0) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00353   }
00354 
00356   //  An exception will be thrown if an attempt is made to persistify any object containing this Ref.
00357   template <typename C, typename T, typename F>
00358   inline
00359   Ref<C, T, F>::Ref(TestHandle<C> const& handle, key_type itemKey, bool setNow) :
00360       ref_(handle.id(), handle.product(), itemKey, 0, 0, true) {
00361     checkTypeAtCompileTime(handle.product());
00362     assert(ref_.item().key() == itemKey);
00363         
00364     if (setNow) {ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));}
00365   }
00366 
00368   template <typename C, typename T, typename F>
00369   inline
00370   Ref<C, T, F>::Ref(RefProd<C> const& refProd, key_type itemKey) :
00371       ref_(refProd.id(), refProd.refCore().productPtr(), itemKey, 0, refProd.refCore().productGetter(), refProd.refCore().isTransient()) {
00372     assert(ref_.item().key() == itemKey);
00373     if (0 != refProd.refCore().productPtr()) {
00374       ref_.item().setPtr(getPtr_<C, T, F>(ref_.refCore(), ref_.item()));
00375     }
00376   }
00377 
00379   // Accessor must get the product if necessary
00380   template <typename C, typename T, typename F>
00381   inline
00382   C const*
00383   Ref<C, T, F>::product() const {
00384       return isNull() ? 0 : edm::template getProduct<C>(ref_.refCore());
00385   }
00386 
00388   template <typename C, typename T, typename F>
00389   inline
00390   T const&
00391   Ref<C, T, F>::operator*() const {
00392     return *getPtr<C, T, F>(ref_.refCore(), ref_.item());
00393   }
00394 
00396   template <typename C, typename T, typename F>
00397   inline
00398   T const*
00399   Ref<C, T, F>::operator->() const {
00400     return getPtr<C, T, F>(ref_.refCore(), ref_.item());
00401   }
00402 
00403   template <typename C, typename T, typename F>
00404   inline
00405   bool
00406   operator==(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00407     return lhs.ref() == rhs.ref();
00408   }
00409 
00410   template <typename C, typename T, typename F>
00411   inline
00412   bool
00413   operator!=(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00414     return !(lhs == rhs);
00415   }
00416 
00417   template <typename C, typename T, typename F>
00418   inline
00419   bool
00420   operator<(Ref<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
00423       return (lhs.ref().refCore() == rhs.ref().refCore() ? compare_key<C>(lhs.key(), rhs.key()) : lhs.ref().refCore() < rhs.ref().refCore());
00424   }
00425 
00426 }
00427 
00428 #include "DataFormats/Common/interface/HolderToVectorTrait.h"
00429 #include "DataFormats/Common/interface/Holder.h"
00430 #include "DataFormats/Common/interface/VectorHolder.h"
00431 #include "DataFormats/Common/interface/RefVector.h"
00432 
00433 namespace edm {
00434   namespace reftobase {
00435 
00436     template <typename T, typename REF>
00437     struct RefHolderToVector {
00438       static  std::auto_ptr<BaseVectorHolder<T> > makeVectorHolder() {
00439         typedef RefVector<typename REF::product_type,
00440                           typename REF::value_type, 
00441                           typename REF::finder_type> REFV;
00442         return std::auto_ptr<BaseVectorHolder<T> >( new VectorHolder<T, REFV> );
00443       }
00444       static  std::auto_ptr<RefVectorHolderBase> makeVectorBaseHolder() {
00445         typedef RefVector<typename REF::product_type,
00446                           typename REF::value_type, 
00447                           typename REF::finder_type> REFV;
00448         return std::auto_ptr<RefVectorHolderBase>( new RefVectorHolder<REFV> );
00449       }
00450     };
00451 
00452     template<typename T1, typename C, typename T, typename F>
00453     struct HolderToVectorTrait<T1, Ref<C, T, F> > {
00454       typedef RefHolderToVector<T1, Ref<C, T, F> > type;
00455     };
00456 
00457     template <typename REF>
00458     struct RefRefHolderToRefVector {
00459       static std::auto_ptr<RefVectorHolderBase> makeVectorHolder() {
00460         typedef RefVector<typename REF::product_type,
00461                           typename REF::value_type, 
00462                                 typename REF::finder_type> REFV;
00463         return std::auto_ptr<RefVectorHolderBase>( new RefVectorHolder<REFV> );
00464       }
00465     };
00466 
00467     template<typename C, typename T, typename F>
00468     struct RefHolderToRefVectorTrait<Ref<C, T, F> > {
00469       typedef RefRefHolderToRefVector<Ref<C, T, F> > type;
00470     };
00471 
00472   }
00473 }
00474   
00475 #endif

Generated on Tue Jun 9 17:29:53 2009 for CMSSW by  doxygen 1.5.4