GetProduct

RefVector

has_fillView

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
#ifndef DataFormats_Common_RefVector_h
#define DataFormats_Common_RefVector_h

/*----------------------------------------------------------------------

RefVector: A template for a vector of interproduct references.
        Each vector element is a reference to a member of the same product.

----------------------------------------------------------------------*/

#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/EDProductfwd.h"
#include "DataFormats/Common/interface/FillView.h"
#include "DataFormats/Common/interface/Ref.h"
#include "DataFormats/Common/interface/RefHolderBase.h"
#include "DataFormats/Common/interface/RefTraits.h"
#include "DataFormats/Common/interface/RefVectorBase.h"
#include "DataFormats/Common/interface/RefVectorIterator.h"
#include "DataFormats/Common/interface/RefVectorTraits.h"
#include "DataFormats/Common/interface/traits.h"
#include "DataFormats/Provenance/interface/ProductID.h"

#include <algorithm>
#include <stdexcept>
#include <vector>

namespace edm {

  template <typename C,
            typename T = typename refhelper::ValueTrait<C>::value,
            typename F = typename refhelper::FindTrait<C, T>::value>
  class RefVector {
  public:
    typedef C collection_type;
    typedef T member_type;
    typedef F finder_type;
    typedef typename refhelper::RefVectorTrait<C, T, F>::iterator_type iterator;
    typedef iterator const_iterator;
    typedef typename refhelper::RefVectorTrait<C, T, F>::ref_type value_type;
    typedef value_type const const_reference;  // better this than the default 'const value_type &'
    typedef const_reference reference;         // as operator[] returns 'const R' and not 'R &'

    // key_type is the type of the key into the collection
    typedef typename value_type::key_type key_type;
    typedef std::vector<key_type> KeyVec;

    // size_type is the type of the index into the RefVector
    typedef typename KeyVec::size_type size_type;
    typedef RefVectorBase<key_type> contents_type;

    /// Default constructor needed for reading from persistent
    /// store. Not for direct use.
    RefVector() : refVector_() {}
    ~RefVector() = default;

    RefVector(RefVector const& rh) : refVector_(rh.refVector_) {}
    RefVector(RefVector&& rh) noexcept : refVector_(std::move(rh.refVector_)) {}

    RefVector& operator=(RefVector const& rhs);
    RefVector& operator=(RefVector&& rhs) noexcept {
      refVector_ = std::move(rhs.refVector_);
      return *this;
    }

    RefVector(ProductID const& iId) : refVector_(iId) {}
    /// Add a Ref<C, T> to the RefVector
    void push_back(value_type const& ref) { refVector_.pushBack(ref.refCore(), ref.key()); }

    /// Retrieve an element of the RefVector
    value_type const operator[](size_type idx) const {
      RefCore const& core = refVector_.refCore();
      key_type const& key = refVector_.keys()[idx];
      void const* memberPointer = refVector_.cachedMemberPointer(idx);
      if (memberPointer) {
        RefCore newCore(core);  // NOLINT
        newCore.setProductPtr(memberPointer);
        return value_type(newCore, key);
      }
      return value_type(core, key);
    }

    /// Retrieve an element of the RefVector
    value_type const at(size_type idx) const {
      RefCore const& core = refVector_.refCore();
      key_type const& key = refVector_.keys().at(idx);
      void const* memberPointer = refVector_.cachedMemberPointer(idx);
      if (memberPointer) {
        RefCore newCore(core);  // NOLINT
        newCore.setProductPtr(memberPointer);
        return value_type(newCore, key);
      }
      return value_type(core, key);
    }

    /// Accessor for all data
    contents_type const& refVector() const { return refVector_; }

    /// Is the RefVector empty
    bool empty() const { return refVector_.empty(); }

    /// Size of the RefVector
    size_type size() const { return refVector_.size(); }

    /// Capacity of the RefVector
    size_type capacity() const { return refVector_.capacity(); }

    /// Reserve space for RefVector
    void reserve(size_type n) { refVector_.reserve(n); }

    /// Initialize an iterator over the RefVector
    const_iterator begin() const;

    /// Termination of iteration
    const_iterator end() const;

    /// Accessor for product ID.
    ProductID id() const { return refVector_.refCore().id(); }

    /// Accessor for product getter
    EDProductGetter const* productGetter() const { return refVector_.refCore().productGetter(); }

    /// Checks for null
    bool isNull() const { return !id().isValid(); }

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

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

    /// Checks if product collection is in memory or available
    /// in the Event. No type checking is done.
    bool isAvailable() const;

    /// Checks if product collection is tansient (i.e. non persistable)
    bool isTransient() const { return refVector_.refCore().isTransient(); }

    /// Erase an element from the vector.
    iterator erase(iterator const& pos);

    /// Clear the vector.
    void clear() { refVector_.clear(); }

    /// Swap two vectors.
    void swap(RefVector<C, T, F>& other) noexcept;

    /// Checks if product is in memory.
    bool hasProductCache() const { return refVector_.refCore().productPtr() != 0; }

    void fillView(ProductID const& id, std::vector<void const*>& pointers, FillViewHelperVector& helpers) const;

    //Needed for ROOT storage
    CMS_CLASS_VERSION(13)

  private:
    contents_type refVector_;
  };

  template <typename C, typename T, typename F>
  inline void RefVector<C, T, F>::swap(RefVector<C, T, F>& other) noexcept {
    refVector_.swap(other.refVector_);
  }

  template <typename C, typename T, typename F>
  inline RefVector<C, T, F>& RefVector<C, T, F>::operator=(RefVector<C, T, F> const& rhs) {
    RefVector<C, T, F> temp(rhs);
    this->swap(temp);
    return *this;
  }

  template <typename C, typename T, typename F>
  inline void swap(RefVector<C, T, F>& a, RefVector<C, T, F>& b) noexcept {
    a.swap(b);
  }

  template <typename C, typename T, typename F>
  void RefVector<C, T, F>::fillView(ProductID const&,
                                    std::vector<void const*>& pointers,
                                    FillViewHelperVector& helpers) const {
    pointers.reserve(this->size());
    helpers.reserve(this->size());

    size_type key = 0;
    for (const_iterator i = begin(), e = end(); i != e; ++i, ++key) {
      member_type const* address = i->isNull() ? nullptr : &**i;
      pointers.push_back(address);
      helpers.emplace_back(i->id(), i->key());
    }
  }

  template <typename C, typename T, typename F>
  inline void fillView(RefVector<C, T, F> const& obj,
                       ProductID const& id,
                       std::vector<void const*>& pointers,
                       FillViewHelperVector& helpers) {
    obj.fillView(id, pointers, helpers);
  }

  template <typename C, typename T, typename F>
  struct has_fillView<RefVector<C, T, F> > {
    static bool const value = true;
  };

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

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

  template <typename C, typename T, typename F>
  inline typename RefVector<C, T, F>::iterator RefVector<C, T, F>::erase(iterator const& pos) {
    typename contents_type::keys_type::size_type index = pos - begin();
    typename contents_type::keys_type::iterator newPos = refVector_.eraseAtIndex(index);
    typename contents_type::keys_type::size_type newIndex = newPos - refVector_.keys().begin();
    return iterator(this, newIndex);
  }

  template <typename C, typename T, typename F>
  typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::begin() const {
    return iterator(this, 0);
  }

  template <typename C, typename T, typename F>
  typename RefVector<C, T, F>::const_iterator RefVector<C, T, F>::end() const {
    return iterator(this, size());
  }

  template <typename C, typename T, typename F>
  bool RefVector<C, T, F>::isAvailable() const {
    if (refVector_.refCore().isAvailable()) {
      return true;
    } else if (empty()) {
      return false;
    }

    // The following is the simplest implementation, but
    // this is woefully inefficient and could be optimized
    // to run much faster with some nontrivial effort. There
    // is only 1 place in the code base where this function
    // is used at all and I'm not sure whether it will ever
    // be used with thinned collections, so for the moment I
    // am not spending the time to optimize this.
    for (size_type i = 0; i < size(); ++i) {
      if (!(*this)[i].isAvailable()) {
        return false;
      }
    }
    return true;
  }

  template <typename C, typename T, typename F>
  std::ostream& operator<<(std::ostream& os, RefVector<C, T, F> const& r) {
    for (typename RefVector<C, T, F>::const_iterator i = r.begin(), e = r.end(); i != e; ++i) {
      os << *i << '\n';
    }
    return os;
  }
}  // namespace edm

#include "DataFormats/Common/interface/GetProduct.h"
namespace edm {
  namespace detail {

    template <typename C, typename T, typename F>
    struct GetProduct<RefVector<C, T, F> > {
      typedef T element_type;
      typedef typename RefVector<C, T, F>::const_iterator iter;
      static element_type const* address(iter const& i) { return &**i; }
    };
  }  // namespace detail
}  // namespace edm
#endif