Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:52:56

0001 #ifndef DataFormats_Common_Association_h
0002 #define DataFormats_Common_Association_h
0003 /* \class Association<RefProd>
0004  *
0005  * \author Luca Lista, INFN
0006  *
0007  *
0008  */
0009 
0010 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0011 #include "DataFormats/Common/interface/Ref.h"
0012 #include "DataFormats/Common/interface/RefProd.h"
0013 #include "DataFormats/Common/interface/ValueMap.h"
0014 
0015 namespace edm {
0016 
0017   template <typename C>
0018   class Association : private ValueMap<int> {
0019   public:
0020     typedef int index;  // negative index == null reference
0021     typedef ValueMap<index> base;
0022     typedef typename base::offset offset;
0023     typedef edm::RefProd<C> refprod_type;  // could be specialized for View
0024     typedef Ref<typename refprod_type::product_type> reference_type;
0025 
0026     Association() : base() {}
0027     template <typename H>
0028     explicit Association(const H& h) : base(), ref_(h) {}
0029 
0030     // import this function from ValueMap<int>
0031     using base::rawIndexOf;
0032 
0033     template <typename RefKey>
0034     reference_type operator[](const RefKey& r) const {
0035       return get(r.id(), r.key());
0036     }
0037 
0038     /// meant to be used internally or in AssociativeIterator, not by the ordinary user
0039     reference_type get(size_t rawIdx) const {
0040       index i = values_[rawIdx];
0041       if (i < 0)
0042         return reference_type();
0043       size_t k = i;
0044       if (k >= ref_->size())
0045         throwIndexMapBound();
0046       return reference_type(ref_, k);
0047     }
0048 
0049     reference_type get(ProductID id, size_t idx) const { return get(rawIndexOf(id, idx)); }
0050 
0051     Association<C>& operator+=(const Association<C>& o) {
0052       add(o);
0053       return *this;
0054     }
0055     void setRef(const refprod_type& ref) {
0056       if (ref_.isNull()) {
0057         ref_ = ref;
0058       } else {
0059         if (ref_.id() != ref.id())
0060           throwRefSet();
0061       }
0062     }
0063     bool contains(ProductID id) const { return base::contains(id); }
0064     size_t size() const { return base::size(); }
0065     bool empty() const { return base::empty(); }
0066     void clear() { base::clear(); }
0067     refprod_type ref() const { return ref_; }
0068     void swap(Association& other) {
0069       this->ValueMap<int>::swap(other);
0070       ref_.swap(other.ref_);
0071     }
0072     Association& operator=(Association const& rhs) {
0073       Association temp(rhs);
0074       this->swap(temp);
0075       return *this;
0076     }
0077 
0078     class Filler : public helper::Filler<Association<C> > {
0079       typedef helper::Filler<Association<C> > base;
0080 
0081     public:
0082       explicit Filler(Association<C>& association) : base(association) {}
0083       void add(const Association<C>& association) {
0084         base::map_.setRef(association.ref());
0085         base::add(association);
0086       }
0087     };
0088 
0089     /// meant to be used in AssociativeIterator, not by the ordinary user
0090     const id_offset_vector& ids() const { return ids_; }
0091     /// meant to be used in AssociativeIterator, not by the ordinary user
0092     using base::id_offset_vector;
0093 
0094     //Used by ROOT storage
0095     CMS_CLASS_VERSION(10)
0096 
0097   private:
0098     refprod_type ref_;
0099     void throwIndexMapBound() const {
0100       Exception::throwThis(errors::InvalidReference, "Association: index in the map out of upper boundary\n");
0101     }
0102     void throwRefSet() const {
0103       Exception::throwThis(errors::InvalidReference, "Association: reference to product already set\n");
0104     }
0105 
0106     void add(const Association<C>& o) {
0107       Filler filler(*this);
0108       filler.add(o);
0109       filler.fill();
0110     }
0111 
0112     friend class helper::Filler<Association<C> >;
0113   };
0114 
0115   // Free swap function
0116   template <typename C>
0117   inline void swap(Association<C>& lhs, Association<C>& rhs) {
0118     lhs.swap(rhs);
0119   }
0120 
0121   template <typename C>
0122   inline Association<C> operator+(const Association<C>& a1, const Association<C>& a2) {
0123     Association<C> a = a1;
0124     a += a2;
0125     return a;
0126   }
0127 }  // namespace edm
0128 
0129 #endif