FwdRef

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
#ifndef DataFormats_Common_FwdRef_h
#define DataFormats_Common_FwdRef_h

/*----------------------------------------------------------------------
  
FwdRef: A template for a interproduct reference to a member of a product.

----------------------------------------------------------------------*/
/**
  \b Summary

  The edm::FwdRef<> is a storable reference to an item in a stored
  "forward" container, which also contains a reference to an item in a
  "backward" container that the "forward" container is derived from.

  For example, you could use one to hold a reference back
  to one particular track within a derived std::vector<> of tracks, 
  but you want to keep the original Ref's to the original
  std::vector<> of tracks (for instance, if you've made a selection
  on the tracks in the list and want to remove the unnecessary ones
  from the event). 
 
  \b Usage
 
  The edm::FwdRef<> works just like a pointer
  \code
     edm::FwdRef<Foo> fooPtr = ... //set the value
     functionTakingConstFoo(*fooPtr); //get the Foo object
     fooPtr->bar();  //call a method of the held Foo object
  \endcode

  The main purpose of an edm::FwdRef<> is it can be used as a member
  datum for a class that is to be stored in the edm::Event where the
  user can simultaneously check the "backwards" ref as well as the
  default "forward" ref. 
 
  \b Customization
 
   The edm::FwdRef<> takes three template parameters, and both
   "forward" and "backward" refs must be the same types:

     1) \b C: The type of the container which is holding the item

     2) \b T: The type of the item.  This defaults to C::value_type

     3) \b F: A helper class (a functor) which knows how to find a
     particular 'T' within the container given an appropriate key. The
     type of the key is deduced from F::second_argument. The default
     for F is refhelper::FindTrait<C,T>::value.  If no specialization
     of FindTrait<> is available for the combination (C,T) then it
     defaults to getting the iterator to be beginning of the container
     and using std::advance() to move to the appropriate key in the
     container.
 
     It is possible to customize the 'lookup' algorithm used.  

     1) The helper class F must provide `value_type`,
     `first_argument_type` and `second_argument_type` typedefs.

     2) The helper class F must define the function call operator in
     such a way that the following call is well-formed:
         // f    is an instance of type F
         // coll is an instance of type C
         // k    is an instance of type F::key_type

         result_type r = f(coll,k);     
 
     If one wishes to make a specialized lookup the default lookup for
     the container/type pair then one needs to partially specialize
     the templated class edm::refhelper::FindTrait<C,T> such that it
     has a typedef named 'value' which refers to the specialized
     helper class (i.e., F)

     The class template FwdRef<C,T,F> supports 'null' references.

     -- a default-constructed FwdRef is 'null'; furthermore, it also
        has an invalid (or 'null') ProductID.
     -- a FwdRef constructed through the single-arguement constructor
        that takes a ProductID is also null.        
*/

/*----------------------------------------------------------------------
//  This defines the public interface to the class FwdRef<C, T, F>.
//  C                         is the collection type.
//  T (default C::value_type) is the type of an element in the collection.
//
//  ProductID productID       is the product ID of the collection.
//  key_type itemKey	      is the key of the element in the collection.
//  C::value_type *itemPtr    is a C++ pointer to the element 
//  FwdRef<C, T, F> const& ref   is another FwdRef<C, T, F>

//  Constructors
    FwdRef(); // Default constructor
    FwdRef(FwdRef<C, T> const& ref);	// Copy constructor  (default, not explicitly specified)

    FwdRef(Ref<C,T,F> const & fwdRef, Ref<C,T,F> const & backRef);

//  Destructor
    virtual ~FwdRef() {}

    // Operators and methods
    FwdRef<C, T>& operator=(FwdRef<C, T> const&);		// assignment (default, not explicitly specified)
    T const& operator*() const;			// dereference
    T const* const operator->() const;		// member dereference
    bool operator==(FwdRef<C, T> const& ref) const; // equality
    bool operator!=(FwdRef<C, T> const& ref) const; // inequality
    bool operator<(FwdRef<C, T> const& ref) const; // ordering
    bool isNonnull() const;			// true if an object is referenced
    bool isNull() const;			// equivalent to !isNonnull()
    bool operator!() const;			// equivalent to !isNonnull()
    ----------------------------------------------------------------------*/

#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/Ref.h"

#include <boost/functional.hpp>

namespace edm {

  template <typename C,
            typename T = typename refhelper::ValueTrait<C>::value,
            typename F = typename refhelper::FindTrait<C, T>::value>
  class FwdRef {
  public:
    /// for export
    typedef C product_type;
    typedef T value_type;
    typedef T const element_type;  //used for generic programming
    typedef F finder_type;
    typedef typename boost::binary_traits<F>::second_argument_type argument_type;
    typedef typename std::remove_cv<typename std::remove_reference<argument_type>::type>::type key_type;
    /// C is the type of the collection
    /// T is the type of a member the collection

    /// Default constructor needed for reading from persistent store. Not for direct use.
    FwdRef() : ref_(), backRef_() {}

    /// General purpose constructor from 2 refs (forward and backward.
    FwdRef(Ref<C, T, F> const& ref, Ref<C, T, F> const& backRef) : ref_(ref), backRef_(backRef) {
      assert(ref.isNull() == backRef.isNull());
    }

    /// Destructor
    ~FwdRef() {}

    /// Dereference operator
    T const& operator*() const;

    /// Member dereference operator
    T const* operator->() const;

    /// Returns C++ pointer to the item
    T const* get() const {
      if (ref_.isAvailable()) {
        return ref_.get();
      } else {
        return backRef_.get();
      }
    }

    /// Checks for null
    bool isNull() const { return !isNonnull(); }

    /// Checks for non-null
    //bool isNonnull() const {return id().isValid(); }
    bool isNonnull() const { return ref_.isNonnull() || backRef_.isNonnull(); }

    /// Checks for null
    bool operator!() const { return isNull(); }

    Ref<C, T, F> const& ref() const { return ref_; }
    Ref<C, T, F> const& backRef() const { return backRef_; }

    /// Accessor for product getter.
    EDProductGetter const* productGetter() const {
      //another thread might cause productGetter() to change its value
      EDProductGetter const* getter = ref_.productGetter();
      if (getter)
        return getter;
      else
        return backRef_.productGetter();
    }

    /// Accessor for product ID.
    ProductID id() const { return ref_.isNonnull() ? ref_.id() : backRef_.id(); }

    /// Accessor for product key.
    key_type key() const { return ref_.isNonnull() ? ref_.key() : backRef_.key(); }

    bool hasProductCache() const { return ref_.hasProductCache() || backRef_.hasProductCache(); }

    /// Checks if collection is in memory or available
    /// in the Event. No type checking is done.
    bool isAvailable() const { return ref_.isAvailable() || backRef_.isAvailable(); }

    /// Checks if this ref is transient (i.e. not persistable).
    bool isTransient() const { return ref_.isTransient(); }

    //Used by ROOT storage
    CMS_CLASS_VERSION(10)

  private:
    Ref<C, T, F> ref_;
    Ref<C, T, F> backRef_;
  };
}  // namespace edm

#include "DataFormats/Common/interface/RefProd.h"

namespace edm {

  /// Dereference operator
  template <typename C, typename T, typename F>
  inline T const& FwdRef<C, T, F>::operator*() const {
    return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator*() : backRef_.operator*();
  }

  /// Member dereference operator
  template <typename C, typename T, typename F>
  inline T const* FwdRef<C, T, F>::operator->() const {
    return ref_.isNonnull() && ref_.isAvailable() ? ref_.operator->() : backRef_.operator->();
  }

  /// for two FwdRefs to be equal, both the
  /// "forward" and the "backward" Refs must be the same
  template <typename C, typename T, typename F>
  inline bool operator==(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return (lhs.ref() == rhs.ref()) && (lhs.backRef() == rhs.backRef());
  }

  /// for a FwdRef to equal a Ref, EITHER the
  /// "forward" or the "backward" Refs must equal to the test ref
  template <typename C, typename T, typename F>
  inline bool operator==(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return (lhs == rhs.ref()) || (lhs == rhs.backRef());
  }

  /// for a FwdRef to equal a Ref, EITHER the
  /// "forward" or the "backward" Refs must equal to the test ref
  template <typename C, typename T, typename F>
  inline bool operator==(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
    return (lhs.ref() == rhs) || (lhs.backRef() == rhs);
  }

  template <typename C, typename T, typename F>
  inline bool operator!=(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return !(lhs == rhs);
  }

  template <typename C, typename T, typename F>
  inline bool operator!=(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return !(lhs == rhs);
  }

  template <typename C, typename T, typename F>
  inline bool operator!=(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
    return !(lhs == rhs);
  }

  /// for inequality operators, ONLY test the forward ref.
  /// the ordering of the backward ref is not relevant.
  template <typename C, typename T, typename F>
  inline bool operator<(FwdRef<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return (lhs.ref() < rhs.ref());
  }

  template <typename C, typename T, typename F>
  inline bool operator<(Ref<C, T, F> const& lhs, FwdRef<C, T, F> const& rhs) {
    return (lhs < rhs.ref());
  }

  template <typename C, typename T, typename F>
  inline bool operator<(FwdRef<C, T, F> const& lhs, Ref<C, T, F> const& rhs) {
    return (lhs.ref() < rhs);
  }

}  // namespace edm

#endif