Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef DataFormats_Common_RefVector_h
0002 #define DataFormats_Common_RefVector_h
0003 
0004 /*----------------------------------------------------------------------
0005 
0006 RefVector: A template for a vector of interproduct references.
0007         Each vector element is a reference to a member of the same product.
0008 
0009 ----------------------------------------------------------------------*/
0010 
0011 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
0012 #include "DataFormats/Common/interface/EDProductfwd.h"
0013 #include "DataFormats/Common/interface/FillView.h"
0014 #include "DataFormats/Common/interface/Ref.h"
0015 #include "DataFormats/Common/interface/RefHolderBase.h"
0016 #include "DataFormats/Common/interface/RefTraits.h"
0017 #include "DataFormats/Common/interface/RefVectorBase.h"
0018 #include "DataFormats/Common/interface/RefVectorIterator.h"
0019 #include "DataFormats/Common/interface/RefVectorTraits.h"
0020 #include "DataFormats/Common/interface/traits.h"
0021 #include "DataFormats/Provenance/interface/ProductID.h"
0022 
0023 #include <algorithm>
0024 #include <stdexcept>
0025 #include <vector>
0026 
0027 namespace edm {
0028 
0029   template <typename C,
0030             typename T = typename refhelper::ValueTrait<C>::value,
0031             typename F = typename refhelper::FindTrait<C, T>::value>
0032   class RefVector {
0033   public:
0034     typedef C collection_type;
0035     typedef T member_type;
0036     typedef F finder_type;
0037     typedef typename refhelper::RefVectorTrait<C, T, F>::iterator_type iterator;
0038     typedef iterator const_iterator;
0039     typedef typename refhelper::RefVectorTrait<C, T, F>::ref_type value_type;
0040     typedef value_type const const_reference;  // better this than the default 'const value_type &'
0041     typedef const_reference reference;         // as operator[] returns 'const R' and not 'R &'
0042 
0043     // key_type is the type of the key into the collection
0044     typedef typename value_type::key_type key_type;
0045     typedef std::vector<key_type> KeyVec;
0046 
0047     // size_type is the type of the index into the RefVector
0048     typedef typename KeyVec::size_type size_type;
0049     typedef RefVectorBase<key_type> contents_type;
0050 
0051     /// Default constructor needed for reading from persistent
0052     /// store. Not for direct use.
0053     RefVector() : refVector_() {}
0054     ~RefVector() = default;
0055 
0056     RefVector(RefVector const& rh) : refVector_(rh.refVector_) {}
0057     RefVector(RefVector&& rh) noexcept : refVector_(std::move(rh.refVector_)) {}
0058 
0059     RefVector& operator=(RefVector const& rhs);
0060     RefVector& operator=(RefVector&& rhs) noexcept {
0061       refVector_ = std::move(rhs.refVector_);
0062       return *this;
0063     }
0064 
0065     RefVector(ProductID const& iId) : refVector_(iId) {}
0066     /// Add a Ref<C, T> to the RefVector
0067     void push_back(value_type const& ref) { refVector_.pushBack(ref.refCore(), ref.key()); }
0068 
0069     /// Retrieve an element of the RefVector
0070     value_type const operator[](size_type idx) const {
0071       RefCore const& core = refVector_.refCore();
0072       key_type const& key = refVector_.keys()[idx];
0073       void const* memberPointer = refVector_.cachedMemberPointer(idx);
0074       if (memberPointer) {
0075         RefCore newCore(core);  // NOLINT
0076         newCore.setProductPtr(memberPointer);
0077         return value_type(newCore, key);
0078       }
0079       return value_type(core, key);
0080     }
0081 
0082     /// Retrieve an element of the RefVector
0083     value_type const at(size_type idx) const {
0084       RefCore const& core = refVector_.refCore();
0085       key_type const& key = refVector_.keys().at(idx);
0086       void const* memberPointer = refVector_.cachedMemberPointer(idx);
0087       if (memberPointer) {
0088         RefCore newCore(core);  // NOLINT
0089         newCore.setProductPtr(memberPointer);
0090         return value_type(newCore, key);
0091       }
0092       return value_type(core, key);
0093     }
0094 
0095     /// Accessor for all data
0096     contents_type const& refVector() const { return refVector_; }
0097 
0098     /// Is the RefVector empty
0099     bool empty() const { return refVector_.empty(); }
0100 
0101     /// Size of the RefVector
0102     size_type size() const { return refVector_.size(); }
0103 
0104     /// Capacity of the RefVector
0105     size_type capacity() const { return refVector_.capacity(); }
0106 
0107     /// Reserve space for RefVector
0108     void reserve(size_type n) { refVector_.reserve(n); }
0109 
0110     /// Initialize an iterator over the RefVector
0111     const_iterator begin() const;
0112 
0113     /// Termination of iteration
0114     const_iterator end() const;
0115 
0116     /// Accessor for product ID.
0117     ProductID id() const { return refVector_.refCore().id(); }
0118 
0119     /// Accessor for product getter
0120     EDProductGetter const* productGetter() const { return refVector_.refCore().productGetter(); }
0121 
0122     /// Checks for null
0123     bool isNull() const { return !id().isValid(); }
0124 
0125     /// Checks for non-null
0126     bool isNonnull() const { return !isNull(); }
0127 
0128     /// Checks for null
0129     bool operator!() const { return isNull(); }
0130 
0131     /// Checks if product collection is in memory or available
0132     /// in the Event. No type checking is done.
0133     bool isAvailable() const;
0134 
0135     /// Checks if product collection is tansient (i.e. non persistable)
0136     bool isTransient() const { return refVector_.refCore().isTransient(); }
0137 
0138     /// Erase an element from the vector.
0139     iterator erase(iterator const& pos);
0140 
0141     /// Clear the vector.
0142     void clear() { refVector_.clear(); }
0143 
0144     /// Swap two vectors.
0145     void swap(RefVector<C, T, F>& other) noexcept;
0146 
0147     /// Checks if product is in memory.
0148     bool hasProductCache() const { return refVector_.refCore().productPtr() != 0; }
0149 
0150     void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;
0151 
0152     //Needed for ROOT storage
0153     CMS_CLASS_VERSION(13)
0154 
0155   private:
0156     contents_type refVector_;
0157   };
0158 
0159   template <typename C, typename T, typename F>
0160   inline void RefVector<C, T, F>::swap(RefVector<C, T, F>& other) noexcept {
0161     refVector_.swap(other.refVector_);
0162   }
0163 
0164   template <typename C, typename T, typename F>
0165   inline RefVector<C, T, F>& RefVector<C, T, F>::operator=(RefVector<C, T, F> const& rhs) {
0166     RefVector<C, T, F> temp(rhs);
0167     this->swap(temp);
0168     return *this;
0169   }
0170 
0171   template <typename C, typename T, typename F>
0172   inline void swap(RefVector<C, T, F>& a, RefVector<C, T, F>& b) noexcept {
0173     a.swap(b);
0174   }
0175 
0176   template <typename C, typename T, typename F>
0177   void RefVector<C, T, F>::fillView(ProductID const&,
0178                                     std::vector<void const*>& pointers,
0179                                     FillViewHelperVector& helpers) const {
0180     pointers.reserve(this->size());
0181     helpers.reserve(this->size());
0182 
0183     size_type key = 0;
0184     for (const_iterator i = begin(), e = end(); i != e; ++i, ++key) {
0185       member_type const* address = i->isNull() ? nullptr : &**i;
0186       pointers.push_back(address);
0187       helpers.emplace_back(i->id(), i->key());
0188     }
0189   }
0190 
0191   template <typename C, typename T, typename F>
0192   inline void fillView(RefVector<C, T, F> const& obj,
0193                        ProductID const& id,
0194                        std::vector<void const*>& pointers,
0195                        FillViewHelperVector& helpers) {
0196     obj.fillView(id, pointers, helpers);
0197   }
0198 
0199   template <typename C, typename T, typename F>
0200   struct has_fillView<RefVector<C, T, F> > {
0201     static bool const value = true;
0202   };
0203 
0204   template <typename C, typename T, typename F>
0205   inline bool operator==(RefVector<C, T, F> const& lhs, RefVector<C, T, F> const& rhs) {
0206     return lhs.refVector() == rhs.refVector();
0207   }
0208 
0209   template <typename C, typename T, typename F>
0210   inline bool operator!=(RefVector<C, T, F> const& lhs, RefVector<C, T, F> const& rhs) {
0211     return !(lhs == rhs);
0212   }
0213 
0214   template <typename C, typename T, typename F>
0215   inline typename RefVector<C, T, F>::iterator RefVector<C, T, F>::erase(iterator const& pos) {
0216     typename contents_type::keys_type::size_type index = pos - begin();
0217     typename contents_type::keys_type::iterator newPos = refVector_.eraseAtIndex(index);
0218     typename contents_type::keys_type::size_type newIndex = newPos - refVector_.keys().begin();
0219     return iterator(this, newIndex);
0220   }
0221 
0222   template <typename C, typename T, typename F>
0223   typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::begin() const {
0224     return iterator(this, 0);
0225   }
0226 
0227   template <typename C, typename T, typename F>
0228   typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::end() const {
0229     return iterator(this, size());
0230   }
0231 
0232   template <typename C, typename T, typename F>
0233   bool RefVector<C, T, F>::isAvailable() const {
0234     if (refVector_.refCore().isAvailable()) {
0235       return true;
0236     } else if (empty()) {
0237       return false;
0238     }
0239 
0240     // The following is the simplest implementation, but
0241     // this is woefully inefficient and could be optimized
0242     // to run much faster with some nontrivial effort. There
0243     // is only 1 place in the code base where this function
0244     // is used at all and I'm not sure whether it will ever
0245     // be used with thinned collections, so for the moment I
0246     // am not spending the time to optimize this.
0247     for (size_type i = 0; i < size(); ++i) {
0248       if (!(*this)[i].isAvailable()) {
0249         return false;
0250       }
0251     }
0252     return true;
0253   }
0254 
0255   template <typename C, typename T, typename F>
0256   std::ostream& operator<<(std::ostream& os, RefVector<C, T, F> const& r) {
0257     for (typename RefVector<C, T, F>::const_iterator i = r.begin(), e = r.end(); i != e; ++i) {
0258       os << *i << '\n';
0259     }
0260     return os;
0261   }
0262 }  // namespace edm
0263 
0264 #include "DataFormats/Common/interface/GetProduct.h"
0265 namespace edm {
0266   namespace detail {
0267 
0268     template <typename C, typename T, typename F>
0269     struct GetProduct<RefVector<C, T, F> > {
0270       typedef T element_type;
0271       typedef typename RefVector<C, T, F>::const_iterator iter;
0272       static element_type const* address(iter const& i) { return &**i; }
0273     };
0274   }  // namespace detail
0275 }  // namespace edm
0276 #endif