LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
id_iterators.h
Go to the documentation of this file.
1 #ifndef LARCOREALG_GEOMETRY_DETAILS_ID_ITERATORS_H
2 #define LARCOREALG_GEOMETRY_DETAILS_ID_ITERATORS_H
3 
4 // LArSoft libraries
8 
9 // C/C++ standard libraries
10 #include <iterator> // std::forward_iterator_tag
11 #include <string>
12 #include <utility>
13 
14 namespace geo::details {
15 
16  template <typename ID>
17  struct id_sentinel {
18  ID id;
19  };
20 
21  template <typename ID>
23 
24  template <typename ID>
25  std::ostream& operator<<(std::ostream& out, id_sentinel<ID> const& sentinel)
26  {
27  return out << "id_sentinel{ " << sentinel.id << " }";
28  }
29 
40  template <typename LocalID, typename GEOID, typename IterationPolicy>
42 
43  template <typename GEOID, typename IterationPolicy>
44  class id_iterator_base<CryostatID, GEOID, IterationPolicy> {
45  public:
46  struct GeometryIDIteratorTag {};
47  using GeoID_t = GEOID;
48 
51 
52  static_assert(std::is_base_of<LocalID_t, GEOID>{}, "template type GEOID is not a LocalID_t");
53 
56  using difference_type = std::ptrdiff_t;
58  using reference = value_type const&;
59  using pointer = value_type const*;
60  using iterator_category = std::forward_iterator_tag;
62 
64  id_iterator_base() = default;
65 
67  id_iterator_base(GeoID_t const& start_from, IterationPolicy policy)
68  : id{start_from}, limit{policy.NSiblings(localID())}
69  {}
70 
72  reference operator*() const { return localID(); }
73  pointer operator->() const { return &localID(); }
74 
77  {
78  next();
79  return *this;
80  }
81 
84  {
85  iterator old(*this);
86  next();
87  return old;
88  }
89 
90  LocalID_t const& localID() const { return ID(); }
91 
92  protected:
93  using ID_t = typename LocalID_t::CryostatID_t;
94 
96  void next()
97  {
98  if (at_end()) return;
99  if (++local_index() < limit) return;
100  }
101 
103  GeoID_t const& ID() const { return id; }
105  GeoID_t& ID() { return id; }
107 
109  bool at_end() const { return local_index() == limit; }
110 
111  private:
112  GeoID_t id{};
113  ID_t limit = LocalID_t::InvalidID;
114 
116  LocalID_t& localID() { return ID(); }
119 
121  ID_t const& local_index() const { return localID().deepestIndex(); }
123  ID_t& local_index() { return localID().deepestIndex(); }
125  }; // class id_iterator_base<CryostatID>
126 
142  template <typename LocalID, typename GEOID, typename IterationPolicy>
143  class id_iterator_base
144  : protected id_iterator_base<typename LocalID::ParentID_t, GEOID, IterationPolicy> {
146 
147  public:
150 
151  using LocalID_t = LocalID;
152  static_assert(std::is_base_of<LocalID_t, GEOID>{}, "template type GEOID is not a LocalID_t");
153 
154  using iterator =
156 
159  using difference_type = std::ptrdiff_t;
161  using reference = value_type const&;
162  using pointer = value_type const*;
163  using iterator_category = std::forward_iterator_tag;
165 
167  id_iterator_base() = default;
168 
170  id_iterator_base(GeoID_t const& start_from, IterationPolicy itPolicy)
171  : upper_iterator{start_from, itPolicy}, policy{itPolicy}, limit(policy.NSiblings(localID()))
172  {}
173 
175  reference operator*() const { return localID(); }
176  pointer operator->() const { return &localID(); }
177 
179  iterator& operator++()
180  {
181  next();
182  return *this;
183  }
184 
186  iterator operator++(int)
187  {
188  iterator old(*this);
189  next();
190  return old;
191  }
192 
193  LocalID_t const& localID() const { return upper_iterator::ID(); }
194 
195  protected:
197  void next()
198  {
199  // if at end (checked in the inherited context), do nothing
200  if (upper_iterator::at_end()) return;
201 
202  // if after incrementing we haven't reached the limit, we are done
203  if (++local_index() < limit) return;
204 
205  // we reached the end of the current elements list, we need to escalate:
206  // - go to the next parent; if that becomes invalid, too bad, but we go on
207  upper_iterator::next();
208  // - set the index to the first element of the new parent
209  local_index() = 0;
210  // - update how many elements there are
211  // (expect 0 if it is now at_end() -- and it does not even matter)
212  limit = policy.NSiblings(localID());
213  }
214 
215  private:
216  IterationPolicy policy;
217 
218  using ID_t = std::decay_t<
219  decltype(std::declval<LocalID_t>().deepestIndex())>;
220 
222  ID_t limit = LocalID_t::InvalidID;
223 
225  LocalID_t& localID() { return upper_iterator::ID(); }
226 
228  ID_t const& local_index() const { return localID().deepestIndex(); }
229  ID_t& local_index() { return localID().deepestIndex(); }
230  }; // class id_iterator_base
231 
232  template <typename LocalID, typename SiblingPolicy>
234 
235  template <typename LocalID, typename SiblingPolicy>
236  auto iterator_for(LocalID const& id, SiblingPolicy const& siblingPolicy)
237  {
238  return id_iterator<LocalID, SiblingPolicy>(id, siblingPolicy);
239  }
240 
242  template <typename T, typename = void>
243  struct has_geometry_id_iterator_tag : std::false_type {};
244 
245  template <typename T>
246  struct has_geometry_id_iterator_tag<T, std::void_t<typename T::GeometryIDIteratorTag>>
247  : std::true_type {};
248 
249  template <typename GEOIT>
251  std::ostream& out,
252  GEOIT const& it)
253  {
254  return out << "geometry_iterator{ " << *it << " }";
255  }
256 
257  template <typename ID, typename Policy>
258  struct supported {
259  static constexpr bool check(unsigned int (Policy::*)(ID const&) const) { return true; }
260  static constexpr bool check(...) { return false; }
261  };
262 
265  template <typename ID, typename IterationPolicy>
266  void IncrementID(ID& id, IterationPolicy const& policy)
267  {
268  static_assert(supported<ID, IterationPolicy>::check(&IterationPolicy::NSiblings));
269 
270  if (++id.deepestIndex() < policy.NSiblings(id)) return;
271  if constexpr (has_parent<ID>::value) {
272  // go to next parent element and reset index
273  id.deepestIndex() = 0;
274  IncrementID(id.parentID(), policy);
275  }
276  }
277 
284  template <typename GeoID, typename IterationPolicy>
285  GeoID GetNextID(GeoID const& id, IterationPolicy const& policy)
286  {
287  auto nextID(id);
288  IncrementID(nextID, policy);
289  return nextID;
290  }
291 
292  // ID iterator/sentinel comparisons
293  template <typename LocalID, typename GeoID, typename IterationPolicy>
296  {
297  return a.localID() == b.localID();
298  }
299 
300  template <typename LocalID, typename GeoID, typename IterationPolicy>
303  {
304  return !(a == b);
305  }
306 
307  template <typename LocalID, typename GeoID, typename IterationPolicy>
309  id_sentinel<LocalID> const& b)
310  {
311  return a.localID() == b.id;
312  }
313 
314  template <typename LocalID, typename GeoID, typename IterationPolicy>
316  id_sentinel<LocalID> const& b)
317  {
318  return !(a == b);
319  }
320 
321  template <typename LocalID, typename GeoID, typename IterationPolicy>
324  {
325  return a.id == b.localID();
326  }
327 
328  template <typename LocalID, typename GeoID, typename IterationPolicy>
331  {
332  return !(a == b);
333  }
334 
335  template <typename LocalID>
337  {
338  return a.id == b.id;
339  }
340 
341  template <typename LocalID>
343  {
344  return !(a == b);
345  }
346 
347 } // namespace geo::details
348 
349 #endif // LARCOREALG_GEOMETRY_DETAILS_ID_ITERATORS_H
IDparameter< geo::CryostatID > CryostatID
Member type of validated geo::CryostatID parameter.
id_iterator_base(GeoID_t const &start_from, IterationPolicy itPolicy)
Constructor: points to the specified element.
Definition: id_iterators.h:170
iterator & operator++()
Prefix increment: returns this iterator pointing to the next cryostat.
Definition: id_iterators.h:76
Classes identifying readout-related concepts.
LocalID_t const & localID() const
Definition: id_iterators.h:193
Base forward iterator browsing all cryostat IDs in the detector.
Definition: id_iterators.h:41
void IncrementID(ID &id, IterationPolicy const &policy)
Definition: id_iterators.h:266
iterator operator++(int)
Postfix increment: returns the current iterator, then increments it.
Definition: id_iterators.h:186
Policy
Enumeration of all supported random seed policies.
Definition: PolicyNames.h:38
ID_t & local_index()
Returns the index (part if the ID) this iterator runs on.
Definition: id_iterators.h:123
bool operator==(geometry_element_iterator< Owner, Element, GEOIDITER > const &a, geometry_element_iterator< Owner, Element, GEOIDITER > const &b)
STL namespace.
value_type const * pointer
Definition: id_iterators.h:162
id_iterator_base(GeoID_t const &start_from, IterationPolicy policy)
Constructor: points to the specified cryostat.
Definition: id_iterators.h:67
LocalID_t & localID()
Returns the type of ID we act on.
Definition: id_iterators.h:225
std::decay_t< decltype(std::declval< LocalID_t >().deepestIndex())> ID_t
specific type for element ID
Definition: id_iterators.h:219
void next()
Skips to the next element.
Definition: id_iterators.h:197
value_type const & reference
Definition: id_iterators.h:161
std::ostream & operator<<(std::ostream &out, id_sentinel< ID > const &sentinel)
Definition: id_iterators.h:25
reference operator*() const
Returns the ID the iterator points to.
Definition: id_iterators.h:72
GeoID_t & ID()
Returns the actual type of ID we store.
Definition: id_iterators.h:105
id_sentinel(ID) -> id_sentinel< ID >
std::forward_iterator_tag iterator_category
Definition: id_iterators.h:163
auto iterator_for(LocalID const &id, SiblingPolicy const &siblingPolicy)
Definition: id_iterators.h:236
Definition of data types for geometry description.
double value
Definition: spectrum.C:18
bool at_end() const
Returns whether this iterator has reached the end.
Definition: id_iterators.h:109
LocalID LocalID_t
type of the ID we change
Definition: id_iterators.h:151
bool operator!=(geometry_element_iterator< Owner, Element, GEOIDITER > const &a, geometry_element_iterator< Owner, Element, GEOIDITER > const &b)
iterator operator++(int)
Postfix increment: returns the current iterator, then increments it.
Definition: id_iterators.h:83
reference operator*() const
Returns the element ID the iterator points to.
Definition: id_iterators.h:175
static constexpr bool check(unsigned int(Policy::*)(ID const &) const)
Definition: id_iterators.h:259
unsigned int CryostatID_t
Type for the ID number.
Definition: geo_types.h:188
Stream output for all geometry ID iterator types: prints the pointed ID.
Definition: id_iterators.h:243
ID_t const & local_index() const
Returns the index (part if the ID) this iterator runs on.
Definition: id_iterators.h:228
typename upper_iterator::GeoID_t GeoID_t
Definition: id_iterators.h:149
static constexpr bool check(...)
Definition: id_iterators.h:260
GeoID GetNextID(GeoID const &id, IterationPolicy const &policy)
Returns the ID next to the specified one.
Definition: id_iterators.h:285
GEOID GeoID_t
type of the actual ID stored in the iterator
Definition: id_iterators.h:47
The data type to uniquely identify a cryostat.
Definition: geo_types.h:187
iterator & operator++()
Prefix increment: returns this iterator pointing to the next element.
Definition: id_iterators.h:179