CMS 3D CMS Logo

DetSetRefVector.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_DetSetRefVector_h
2 #define DataFormats_Common_DetSetRefVector_h
3 
4 /*----------------------------------------------------------------------
5 
6 DetSeReftVector: A collection of homogeneous objects that can be used for
7 an EDProduct. DetSetVector is *not* designed for use as a base class
8 (it has no virtual functions).
9 
10 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
11 provides fast (O(log n)) lookups, but only O(n) insertion.
12 
13 It provides an interface such that EdmRef2 can directly reference, and
14 provide access to, individual T objects.
15 
16 The collection appears to the user as if it were a sequence of
17 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
18 argument to operator[] specifies the (DetId) identifier of the vector
19 to be returned, *not* the ordinal number of the T to be returned.
20 
21  ------------------
22  It is critical that users DO NOT MODIFY the id data member of a
23  DetSet object in a DetSetVector.
24  ------------------
25 
26 ----------------------------------------------------------------------*/
27 
28 #include <algorithm>
29 #include <vector>
30 
31 #include "boost/concept_check.hpp"
32 #include "boost/iterator/indirect_iterator.hpp"
33 
38 
44 
45 namespace edm {
46 
47  //------------------------------------------------------------
48  // Forward declarations
49  template <typename T, typename C>
51 
52  //------------------------------------------------------------
53  // Helper function, to regularize throwing of exceptions.
54  //------------------------------------------------------------
55 
56  namespace dsrvdetail {
57  // Throw an edm::Exception with an appropriate message
58  inline void _throw_range(det_id_type i) {
60  "DetSetRefVector::operator[] called with index not in collection;\nindex value: ",
61  i);
62  }
63  } // namespace dsrvdetail
64 
65  //------------------------------------------------------------
66  //
67  namespace refhelper {
68  template <typename T, typename C>
70  using result_type = DetSet<T> const*;
71  using first_argument_type = C const&;
73 
75  return &(*(iContainer.find(iIndex)));
76  }
77  };
78  } // namespace refhelper
79 
80  //allow comparison of edm::Ref<...> to the det_it_type. This allows searching without dereferencing the edm::Ref
81  template <typename T, typename C = DetSetVector<T> >
84  bool operator()(const ref_type& iRef, det_id_type iId) { return iRef.key() < iId; }
85  bool operator()(det_id_type iId, const ref_type& iRef) { return iId < iRef.key(); }
86  };
87 
88  template <typename T, typename C = DetSetVector<T> >
89  class DetSetRefVector {
92  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
93 
94  public:
95  typedef DetSet<T> detset;
96  typedef detset value_type;
98  typedef std::vector<ref_type> collection_type;
99 
100  typedef detset const& const_reference;
101 
102  //iterator returns a DetSet<T> instead of a Ref<...>
103  typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
105 
108 
109  // Add the following only if needed.
110  //template <class InputIterator>
111  //DetSetRefVector(InputIterator b, InputIterator e);
112 
114 
115  DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
116  sets_.reserve(iDets.size());
117  det_id_type sanityCheck = 0;
118  for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
119  itDetId != itDetIdEnd;
120  ++itDetId) {
121  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
122  sanityCheck = *itDetId;
123  //the last 'false' says to not get the data right now
124  sets_.push_back(ref_type(iHandle, *itDetId, false));
125  }
126  }
127 
128  DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
129  sets_.reserve(iDets.size());
130  det_id_type sanityCheck = 0;
131  for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
132  itDetId != itDetIdEnd;
133  ++itDetId) {
134  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
135  sanityCheck = *itDetId;
136  //the last 'false' says to not get the data right now
137  sets_.push_back(ref_type(iHandle, *itDetId, false));
138  }
139  }
140 
141  DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
142  sets_.reserve(iDets.size());
143  det_id_type sanityCheck = 0;
144  for (std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
145  itDetId != itDetIdEnd;
146  ++itDetId) {
147  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
148  sanityCheck = *itDetId;
149  //the last 'false' says to not get the data right now
150  sets_.push_back(ref_type(iHandle, *itDetId, false));
151  }
152  }
153 
154  void swap(DetSetRefVector& other);
155 
157 
159  bool empty() const;
160 
162  size_type size() const;
163 
164  // Do we need a short-hand method to return the number of T
165  // instances? If so, do we optimize for size (calculate on the
166  // fly) or speed (keep a current cache)?
167 
170  const_iterator find(det_id_type id) const;
171 
176 
178  const_iterator begin() const;
179 
181  const_iterator end() const;
182 
185  //void post_insert();
186 
187  //Needed for ROOT storage
189 
190  private:
192  };
193 
194  template <typename T, typename C>
196  sets_.swap(other.sets_);
197  }
198 
199  template <typename T, typename C>
202  this->swap(temp);
203  return *this;
204  }
205 
206  template <typename T, typename C>
207  inline bool DetSetRefVector<T, C>::empty() const {
208  return sets_.empty();
209  }
210 
211  template <typename T, typename C>
213  return sets_.size();
214  }
215 
216  template <typename T, typename C>
218  if (empty()) {
219  return sets_.end();
220  }
221  std::pair<typename collection_type::const_iterator, typename collection_type::const_iterator> p =
222  std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T, C>());
223  if (p.first == p.second)
224  return sets_.end();
225  // The range indicated by [p.first, p.second) should be exactly of
226  // length 1.
227  assert(std::distance(p.first, p.second) == 1);
228  return p.first;
229  }
230 
231  template <typename T, typename C>
233  // Find the right DetSet, and return a reference to it. Throw if
234  // there is none.
235  const_iterator it = this->find(i);
236  if (it == this->end())
238  return *it;
239  }
240 
241  template <typename T, typename C>
243  return sets_.begin();
244  }
245 
246  template <typename T, typename C>
248  return sets_.end();
249  }
250 
251  // Free swap function
252  template <typename T, typename C>
254  a.swap(b);
255  }
256 
257  //specialize behavior of edm::Ref to get access to the 'Det'
258 
259  namespace refhelper {
260  template <typename T, typename C>
262  using result_type = T const*;
265 
267  return &(*(iContainer.find(iIndex.first)->data.begin() + iIndex.second));
268  }
269  };
270 
271  template <typename T, typename C>
274  };
275  } // namespace refhelper
276 
277  //helper function to make it easier to create a edm::Ref
278 
279  template <class HandleT>
281  const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter) {
282  typedef typename HandleT::element_type Vec;
284  typename Vec::const_iterator itFound = iHandle->find(iDetID);
285  index += (itIter - itFound->data.begin());
287  iHandle, std::make_pair(iDetID, index));
288  }
289 
290  template <class HandleT>
292  const HandleT& iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::iterator itIter) {
293  typedef typename HandleT::element_type Vec;
294  typename Vec::detset::const_iterator itIter2 = itIter;
295  return makeRefToDetSetRefVector(iHandle, iDetID, itIter2);
296  }
297 } // namespace edm
298 #endif
Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type > makeRefToDetSetRefVector(const HandleT &iHandle, det_id_type iDetID, typename HandleT::element_type::value_type::const_iterator itIter)
Ref< C, DetSet< T >, refhelper::FindDetSetForDetSetVector< T, C > > ref_type
size_type size() const
Return the number of contained DetSets.
Definition: CLHEP.h:16
const_iterator end() const
Return the off-the-end iterator.
DetSetRefVector(const OrphanHandle< C > &iHandle, const std::vector< det_id_type > &iDets)
#define CMS_CLASS_VERSION(_version_)
assert(be >=bs)
result_type operator()(first_argument_type iContainer, second_argument_type iIndex)
uint16_t size_type
DetSetRefVector(const Handle< C > &iHandle, const std::vector< det_id_type > &iDets)
key_type key() const
Accessor for product key.
Definition: Ref.h:250
result_type operator()(first_argument_type iContainer, second_argument_type iIndex) const
void _throw_range(det_id_type i)
std::vector< ref_type > collection_type
static void throwThis(Code category, char const *message0="", char const *message1="", char const *message2="", char const *message3="", char const *message4="")
Definition: EDMException.cc:86
detset const & const_reference
DetSetRefVector & operator=(DetSetRefVector const &rhs)
collection_type sets_
bool operator()(const ref_type &iRef, det_id_type iId)
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:521
bool operator()(det_id_type iId, const ref_type &iRef)
std::pair< det_id_type, typename DetSet< T >::collection_type::size_type > second_argument_type
const_iterator find(det_id_type id) const
collection_type::size_type size_type
uint32_t det_id_type
Definition: DetSet.h:20
const_reference operator[](det_id_type i) const
const_iterator begin() const
Return an iterator to the first DetSet.
bool empty() const
Return true if we contain no DetSets.
double b
Definition: hdecay.h:120
alpaka::Vec< TDim, Idx > Vec
Definition: config.h:23
void swap(DetSetRefVector &other)
BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept)
HLT enums.
double a
Definition: hdecay.h:121
Ref< C, DetSet< T >, refhelper::FindDetSetForDetSetVector< T, C > > ref_type
boost::indirect_iterator< typename collection_type::const_iterator > const_iterator
long double T
DetSetRefVector(const TestHandle< C > &iHandle, const std::vector< det_id_type > &iDets)