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> class DetSetRefVector;
50 
51  //------------------------------------------------------------
52  // Helper function, to regularize throwing of exceptions.
53  //------------------------------------------------------------
54 
55  namespace dsrvdetail
56  {
57  // Throw an edm::Exception with an appropriate message
58  inline
60  {
62  "DetSetRefVector::operator[] called with index not in collection;\nindex value: ", i);
63  }
64  }
65 
66  //------------------------------------------------------------
67  //
68  namespace refhelper {
69  template<typename T, typename C >
70  struct FindDetSetForDetSetVector : public std::binary_function<const C &, edm::det_id_type, const DetSet<T>*> {
72  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const {
73  return &(*(iContainer.find(iIndex)));
74  }
75  };
76  }
77 
78  //allow comparison of edm::Ref<...> to the det_it_type. This allows searching without dereferencing the edm::Ref
79  template <typename T, typename C=DetSetVector<T> >
82  bool operator()(const ref_type& iRef, det_id_type iId) {
83  return iRef.key() < iId;
84  }
85  bool operator()(det_id_type iId, const ref_type& iRef) {
86  return iId < iRef.key();
87  }
88  };
89 
90  template <typename T, typename C=DetSetVector<T> >
91  class DetSetRefVector
92  {
95  BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
96  public:
97 
98  typedef DetSet<T> detset;
99  typedef detset value_type;
101  typedef std::vector<ref_type> collection_type;
102 
103  typedef detset const& const_reference;
104 
105  //iterator returns a DetSet<T> instead of a Ref<...>
106  typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
108 
111 
112  // Add the following only if needed.
113  //template <class InputIterator>
114  //DetSetRefVector(InputIterator b, InputIterator e);
115 
117 
118  DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
119  sets_.reserve(iDets.size());
120  det_id_type sanityCheck = 0;
121  for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
122  itDetIdEnd = iDets.end();
123  itDetId != itDetIdEnd;
124  ++itDetId) {
125  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
126  sanityCheck = *itDetId;
127  //the last 'false' says to not get the data right now
128  sets_.push_back(ref_type(iHandle, *itDetId, false));
129  }
130  }
131 
132  DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
133  sets_.reserve(iDets.size());
134  det_id_type sanityCheck = 0;
135  for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
136  itDetIdEnd = iDets.end();
137  itDetId != itDetIdEnd;
138  ++itDetId) {
139  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
140  sanityCheck = *itDetId;
141  //the last 'false' says to not get the data right now
142  sets_.push_back(ref_type(iHandle, *itDetId, false));
143  }
144  }
145 
146  DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
147  sets_.reserve(iDets.size());
148  det_id_type sanityCheck = 0;
149  for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
150  itDetIdEnd = iDets.end();
151  itDetId != itDetIdEnd;
152  ++itDetId) {
153  assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
154  sanityCheck = *itDetId;
155  //the last 'false' says to not get the data right now
156  sets_.push_back(ref_type(iHandle, *itDetId, false));
157  }
158  }
159 
160  void swap(DetSetRefVector& other);
161 
162  DetSetRefVector& operator=(DetSetRefVector const& rhs);
163 
165  bool empty() const;
166 
168  size_type size() const;
169 
170  // Do we need a short-hand method to return the number of T
171  // instances? If so, do we optimize for size (calculate on the
172  // fly) or speed (keep a current cache)?
173 
176  const_iterator find(det_id_type id) const;
177 
181  const_reference operator[](det_id_type i) const;
182 
184  const_iterator begin() const;
185 
187  const_iterator end() const;
188 
191  //void post_insert();
192 
193  //Needed for ROOT storage
195 
196  private:
197  collection_type sets_;
198 
199  };
200 
201  template <typename T, typename C>
202  inline
203  void
204  DetSetRefVector<T,C>::swap(DetSetRefVector<T,C>& other) {
205  sets_.swap(other.sets_);
206  }
207 
208  template <typename T, typename C>
209  inline
213  this->swap(temp);
214  return *this;
215  }
216 
217  template <typename T, typename C>
218  inline
219  bool
221  {
222  return sets_.empty();
223  }
224 
225  template <typename T, typename C>
226  inline
229  {
230  return sets_.size();
231  }
232 
233  template <typename T, typename C>
234  inline
237  {
238  if(empty()) {
239  return sets_.end();
240  }
241  std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p =
242  std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T,C>());
243  if (p.first == p.second) return sets_.end();
244  // The range indicated by [p.first, p.second) should be exactly of
245  // length 1.
246  assert(std::distance(p.first, p.second) == 1);
247  return p.first;
248  }
249 
250  template <typename T, typename C>
251  inline
254  {
255  // Find the right DetSet, and return a reference to it. Throw if
256  // there is none.
257  const_iterator it = this->find(i);
258  if (it == this->end()) dsrvdetail::_throw_range(i);
259  return *it;
260  }
261 
262  template <typename T, typename C>
263  inline
266  {
267  return sets_.begin();
268  }
269 
270  template <typename T, typename C>
271  inline
274  {
275  return sets_.end();
276  }
277 
278  // Free swap function
279  template <typename T, typename C>
280  inline
281  void
283  a.swap(b);
284  }
285 
286 //specialize behavior of edm::Ref to get access to the 'Det'
287 
288  namespace refhelper {
289  template<typename T, typename C>
290  struct FindForDetSetRefVector : public std::binary_function<const DetSetRefVector<T,C>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
292  typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
293  return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
294  }
295  };
296 
297  template<typename T, typename C>
300  };
301  }
302 
303  //helper function to make it easier to create a edm::Ref
304 
305  template<class HandleT>
307  makeRefToDetSetRefVector(const HandleT& iHandle,
308  det_id_type iDetID,
309  typename HandleT::element_type::value_type::const_iterator itIter) {
310  typedef typename HandleT::element_type Vec;
312  typename Vec::const_iterator itFound = iHandle->find(iDetID);
313  index += (itIter- itFound->data.begin());
315  }
316 
317  template<class HandleT>
319  makeRefToDetSetRefVector(const HandleT& iHandle,
320  det_id_type iDetID,
321  typename HandleT::element_type::value_type::iterator itIter) {
322  typedef typename HandleT::element_type Vec;
323  typename Vec::detset::const_iterator itIter2 = itIter;
324  return makeRefToDetSetRefVector(iHandle,iDetID,itIter2);
325  }
326 }
327 #endif
size
Write out results.
DetSetRefVector & operator=(DetSetRefVector const &rhs)
Definition: CLHEP.h:16
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)
DetSetRefVector(const OrphanHandle< C > &iHandle, const std::vector< det_id_type > &iDets)
key_type key() const
Accessor for product key.
Definition: Ref.h:265
#define CMS_CLASS_VERSION(_version_)
Definition: classes.h:31
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
const_iterator find(det_id_type id) const
uint16_t size_type
DetSetRefVector(const Handle< C > &iHandle, const std::vector< det_id_type > &iDets)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
Ref< C, DetSet< T >, refhelper::FindDetSetForDetSetVector< T, C > > ref_type
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="")
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex)
detset const & const_reference
const_iterator begin() const
Return an iterator to the first DetSet.
bool operator()(const ref_type &iRef, det_id_type iId)
bool empty() const
Return true if we contain no DetSets.
T operator[](int i) const
def template(fileName, svg, replaceme="REPLACEME")
Definition: svgfig.py:520
const_reference operator[](det_id_type i) const
bool operator()(det_id_type iId, const ref_type &iRef)
#define end
Definition: vmac.h:39
collection_type::size_type size_type
uint32_t det_id_type
Definition: DetSet.h:21
Ref< C, DetSet< T >, refhelper::FindDetSetForDetSetVector< T, C > > ref_type
double b
Definition: hdecay.h:120
size_type size() const
Return the number of contained DetSets.
void swap(DetSetRefVector &other)
#define begin
Definition: vmac.h:32
HLT enums.
double a
Definition: hdecay.h:121
boost::indirect_iterator< typename collection_type::const_iterator > const_iterator
const_iterator end() const
Return the off-the-end iterator.
long double T
self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const
DetSetRefVector(const TestHandle< C > &iHandle, const std::vector< det_id_type > &iDets)