Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:51

0001 #ifndef DataFormats_Common_FwdRef_h
0002 #define DataFormats_Common_FwdRef_h
0003 
0004 /*----------------------------------------------------------------------
0005   
0006 FwdRef: A template for a interproduct reference to a member of a product.
0007 
0008 ----------------------------------------------------------------------*/
0009 /**
0010   \b Summary
0011 
0012   The edm::FwdRef<> is a storable reference to an item in a stored
0013   "forward" container, which also contains a reference to an item in a
0014   "backward" container that the "forward" container is derived from.
0015 
0016   For example, you could use one to hold a reference back
0017   to one particular track within a derived std::vector<> of tracks, 
0018   but you want to keep the original Ref's to the original
0019   std::vector<> of tracks (for instance, if you've made a selection
0020   on the tracks in the list and want to remove the unnecessary ones
0021   from the event). 
0022  
0023   \b Usage
0024  
0025   The edm::FwdRef<> works just like a pointer
0026   \code
0027      edm::FwdRef<Foo> fooPtr = ... //set the value
0028      functionTakingConstFoo(*fooPtr); //get the Foo object
0029      fooPtr->bar();  //call a method of the held Foo object
0030   \endcode
0031 
0032   The main purpose of an edm::FwdRef<> is it can be used as a member
0033   datum for a class that is to be stored in the edm::Event where the
0034   user can simultaneously check the "backwards" ref as well as the
0035   default "forward" ref. 
0036  
0037   \b Customization
0038  
0039    The edm::FwdRef<> takes three template parameters, and both
0040    "forward" and "backward" refs must be the same types:
0041 
0042      1) \b C: The type of the container which is holding the item
0043 
0044      2) \b T: The type of the item.  This defaults to C::value_type
0045 
0046      3) \b F: A helper class (a functor) which knows how to find a
0047      particular 'T' within the container given an appropriate key. The
0048      type of the key is deduced from F::second_argument. The default
0049      for F is refhelper::FindTrait<C,T>::value.  If no specialization
0050      of FindTrait<> is available for the combination (C,T) then it
0051      defaults to getting the iterator to be beginning of the container
0052      and using std::advance() to move to the appropriate key in the
0053      container.
0054  
0055      It is possible to customize the 'lookup' algorithm used.  
0056 
0057      1) The helper class F must provide `value_type`,
0058      `first_argument_type` and `second_argument_type` typedefs.
0059 
0060      2) The helper class F must define the function call operator in
0061      such a way that the following call is well-formed:
0062          // f    is an instance of type F
0063          // coll is an instance of type C
0064          // k    is an instance of type F::key_type
0065 
0066          result_type r = f(coll,k);     
0067  
0068      If one wishes to make a specialized lookup the default lookup for
0069      the container/type pair then one needs to partially specialize
0070      the templated class edm::refhelper::FindTrait<C,T> such that it
0071      has a typedef named 'value' which refers to the specialized
0072      helper class (i.e., F)
0073 
0074      The class template FwdRef<C,T,F> supports 'null' references.
0075 
0076      -- a default-constructed FwdRef is 'null'; furthermore, it also
0077         has an invalid (or 'null') ProductID.
0078      -- a FwdRef constructed through the single-arguement constructor
0079         that takes a ProductID is also null.        
0080 */
0081 
0082 /*----------------------------------------------------------------------
0083 //  This defines the public interface to the class FwdRef<C, T, F>.
0084 //  C                         is the collection type.
0085 //  T (default C::value_type) is the type of an element in the collection.
0086 //
0087 //  ProductID productID       is the product ID of the collection.
0088 //  key_type itemKey          is the key of the element in the collection.
0089 //  C::value_type *itemPtr    is a C++ pointer to the element 
0090 //  FwdRef<C, T, F> const& ref   is another FwdRef<C, T, F>
0091 
0092 //  Constructors
0093     FwdRef(); // Default constructor
0094     FwdRef(FwdRef<C, T> const& ref);    // Copy constructor  (default, not explicitly specified)
0095 
0096     FwdRef(Ref<C,T,F> const & fwdRef, Ref<C,T,F> const & backRef);
0097 
0098 //  Destructor
0099     virtual ~FwdRef() {}
0100 
0101     // Operators and methods
0102     FwdRef<C, T>& operator=(FwdRef<C, T> const&);       // assignment (default, not explicitly specified)
0103     T const& operator*() const;         // dereference
0104     T const* const operator->() const;      // member dereference
0105     bool operator==(FwdRef<C, T> const& ref) const; // equality
0106     bool operator!=(FwdRef<C, T> const& ref) const; // inequality
0107     bool operator<(FwdRef<C, T> const& ref) const; // ordering
0108     bool isNonnull() const;         // true if an object is referenced
0109     bool isNull() const;            // equivalent to !isNonnull()
0110     bool operator!() const;         // equivalent to !isNonnull()
0111     ----------------------------------------------------------------------*/
0112 
0113 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0114 #include "DataFormats/Common/interface/Ref.h"
0115 
0116 #include <boost/functional.hpp>
0117 
0118 namespace edm {
0119 
0120   template <typename C,
0121             typename T = typename refhelper::ValueTrait<C>::value,
0122             typename F = typename refhelper::FindTrait<C, T>::value>
0123   class FwdRef {
0124   public:
0125     /// for export
0126     typedef C product_type;
0127     typedef T value_type;
0128     typedef T const element_type;  //used for generic programming
0129     typedef F finder_type;
0130     typedef typename boost::binary_traits<F>::second_argument_type argument_type;
0131     typedef typename std::remove_cv<typename std::remove_reference<argument_type>::type>::type key_type;
0132     /// C is the type of the collection
0133     /// T is the type of a member the collection
0134 
0135     /// Default constructor needed for reading from persistent store. Not for direct use.
0136     FwdRef() : ref_(), backRef_() {}
0137 
0138     /// General purpose constructor from 2 refs (forward and backward.
0139     FwdRef(Ref<C, T, F> const& ref, Ref<C, T, F> const& backRef) : ref_(ref), backRef_(backRef) {
0140       assert(ref.isNull() == backRef.isNull());
0141     }
0142 
0143     /// Destructor
0144     ~FwdRef() {}
0145 
0146     /// Dereference operator
0147     T const& operator*() const;
0148 
0149     /// Member dereference operator
0150     T const* operator->() const;
0151 
0152     /// Returns C++ pointer to the item
0153     T const* get() const {
0154       if (ref_.isAvailable()) {
0155         return ref_.get();
0156       } else {
0157         return backRef_.get();
0158       }
0159     }
0160 
0161     /// Checks for null
0162     bool isNull() const { return !isNonnull(); }
0163 
0164     /// Checks for non-null
0165     //bool isNonnull() const {return id().isValid(); }
0166     bool isNonnull() const { return ref_.isNonnull() || backRef_.isNonnull(); }
0167 
0168     /// Checks for null
0169     bool operator!() const { return isNull(); }
0170 
0171     Ref<C, T, F> const& ref() const { return ref_; }
0172     Ref<C, T, F> const& backRef() const { return backRef_; }
0173 
0174     /// Accessor for product getter.
0175     EDProductGetter const* productGetter() const {
0176       //another thread might cause productGetter() to change its value
0177       EDProductGetter const* getter = ref_.productGetter();
0178       if (getter)
0179         return getter;
0180       else
0181         return backRef_.productGetter();
0182     }
0183 
0184     /// Accessor for product ID.
0185     ProductID id() const { return ref_.isNonnull() ? ref_.id() : backRef_.id(); }
0186 
0187     /// Accessor for product key.
0188     key_type key() const { return ref_.isNonnull() ? ref_.key() : backRef_.key(); }
0189 
0190     bool hasProductCache() const { return ref_.hasProductCache() || backRef_.hasProductCache(); }
0191 
0192     /// Checks if collection is in memory or available
0193     /// in the Event. No type checking is done.
0194     bool isAvailable() const { return ref_.isAvailable() || backRef_.isAvailable(); }
0195 
0196     /// Checks if this ref is transient (i.e. not persistable).
0197     bool isTransient() const { return ref_.isTransient(); }
0198 
0199     //Used by ROOT storage
0200     CMS_CLASS_VERSION(10)
0201 
0202   private:
0203     Ref<C, T, F> ref_;
0204     Ref<C, T, F> backRef_;
0205   };
0206 }  // namespace edm
0207 
0208 #include "DataFormats/Common/interface/RefProd.h"
0209 
0210 namespace edm {
0211 
0212   /// Dereference operator
0213   template <typename C, typename T, typename F>
0214   inline T const& FwdRef<C, T, F>::operator*() const {
0215     return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator*() : backRef_.operator*();
0216   }
0217 
0218   /// Member dereference operator
0219   template <typename C, typename T, typename F>
0220   inline T const* FwdRef<C, T, F>::operator->() const {
0221     return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator->() : backRef_.operator->();
0222   }
0223 
0224   /// for two FwdRefs to be equal, both the
0225   /// "forward" and the "backward" Refs must be the same
0226   template <typename C, typename T, typename F>
0227   inline bool operator==(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0228     return (lhs.ref() == rhs.ref()) && (lhs.backRef() == rhs.backRef());
0229   }
0230 
0231   /// for a FwdRef to equal a Ref, EITHER the
0232   /// "forward" or the "backward" Refs must equal to the test ref
0233   template <typename C, typename T, typename F>
0234   inline bool operator==(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0235     return (lhs == rhs.ref()) || (lhs == rhs.backRef());
0236   }
0237 
0238   /// for a FwdRef to equal a Ref, EITHER the
0239   /// "forward" or the "backward" Refs must equal to the test ref
0240   template <typename C, typename T, typename F>
0241   inline bool operator==(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
0242     return (lhs.ref() == rhs) || (lhs.backRef() == rhs);
0243   }
0244 
0245   template <typename C, typename T, typename F>
0246   inline bool operator!=(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0247     return !(lhs == rhs);
0248   }
0249 
0250   template <typename C, typename T, typename F>
0251   inline bool operator!=(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0252     return !(lhs == rhs);
0253   }
0254 
0255   template <typename C, typename T, typename F>
0256   inline bool operator!=(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
0257     return !(lhs == rhs);
0258   }
0259 
0260   /// for inequality operators, ONLY test the forward ref.
0261   /// the ordering of the backward ref is not relevant.
0262   template <typename C, typename T, typename F>
0263   inline bool operator<(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0264     return (lhs.ref() < rhs.ref());
0265   }
0266 
0267   template <typename C, typename T, typename F>
0268   inline bool operator<(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
0269     return (lhs < rhs.ref());
0270   }
0271 
0272   template <typename C, typename T, typename F>
0273   inline bool operator<(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
0274     return (lhs.ref() < rhs);
0275   }
0276 
0277 }  // namespace edm
0278 
0279 #endif