LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
NestedIterator.h
Go to the documentation of this file.
1 
11 #ifndef NESTEDITERATOR_H
12 #define NESTEDITERATOR_H
13 
14 // interface include
15 #include <type_traits> // std::true_type, std::false_type, std::conditional
16 #include <iterator> // std::forward_iterator_tag
17 
18 namespace lar {
19 
20  namespace details {
21  namespace type_traits {
22 
23  //------------------------------------------------------------------------
24  // declarations of helpers for has_const_iterator() function
25  template <typename T, bool>
27 
28  template <typename T>
29  constexpr auto has_const_iterator_helper(T* = nullptr)
30  -> decltype(typename T::const_iterator(), bool());
31 
32  // Used as fallback when SFINAE culls the template method
33  constexpr bool has_const_iterator_helper(...);
34  //------------------------------------------------------------------------
35 
36  } // namespace type_traits
37  } // namespace details
38 
39  template <typename T>
42  <T, details::type_traits::has_const_iterator_helper((T*)(nullptr))>
43  {};
44 
45 
47  template <typename T>
48  class Identity;
49 
50 
51  template <typename T>
52  class PairSecond;
53 
55  template <
56  typename ITER,
57  typename INNERCONTEXTRACT = Identity<typename ITER::value_type>
58  >
60 
61 
64 /* template <typename CITER>
65  using deep_fwd_const_iterator = std::conditional<
66  has_const_iterator<typename CITER::value_type>(),
67  deep_const_fwd_iterator_nested<CITER>,
68  CITER
69  >;
70 */
71 
72  template <
73  typename CITER,
74  typename INNERCONTEXTRACT = Identity<typename CITER::value_type>
75  >
78 
79 } // namespace lar
80 
81 
82 namespace std {
83  template <typename CITER, typename INNERCONTEXTRACT>
86 
87 } // namespace std
88 
89 
90 //------------------------------------------------------------------------------
91 
92 namespace lar {
93 
94  namespace details {
95  namespace type_traits {
96 
97  //------------------------------------------------------------------------
98  // helpers for has_const_iterator() function
99  template <typename T, bool>
100  struct has_const_iterator_struct: public std::false_type {};
101 
102  template <typename T>
103  struct has_const_iterator_struct<T, true>: public std::true_type {};
104 
105  // Culled by SFINAE if T::const_iterator does not exist
106  // or is not accessible or not default-constructable
107  template <typename T>
108  constexpr auto has_const_iterator_helper(T* /* = nullptr */)
109  -> decltype(typename T::const_iterator(), bool())
110  { return true; }
111 
112  // Used as fallback when SFINAE culls the template method
113  constexpr bool has_const_iterator_helper(...) { return false; }
114  //------------------------------------------------------------------------
115 
116  } // namespace type_traits
117  } // namespace details
118 
119  //---
120  //--- Identity declaration
121  //---
122  template <class T>
123  class Identity {
124  public:
125  typedef T argument_type;
126  typedef T result_type;
127 
128  result_type& operator() (argument_type& x) const { return x; }
129  const result_type& operator() (const argument_type& x) const { return x; }
130  }; // class Identity<>
131 
132 
133  //---
134  //--- PairSecond declaration
135  //---
136  template <class T>
137  class PairSecond {
138  public:
139  typedef T argument_type;
140  typedef typename T::second_type result_type;
141 
142  result_type& operator() (argument_type& p) const
143  { return p.second; }
144  const result_type& operator() (const argument_type& p) const
145  { return p.second; }
146  }; // class PairSecond<>
147 
148 
149  //---
150  //--- deep_const_fwd_iterator_nested declaration
151  //---
152  template <typename ITER, typename INNERCONTEXTRACT>
153  class deep_const_fwd_iterator_nested: public std::forward_iterator_tag {
154  public:
155  using OuterIterator_t = ITER;
156  using InnerContainerExtractor_t = INNERCONTEXTRACT;
157  using InnerContainer_t = typename InnerContainerExtractor_t::result_type;
158  using InnerIterator_t
159  // = deep_fwd_const_iterator<typename ITER::value_type::const_iterator>;
161 
162  // using iterator_type = deep_fwd_const_iterator<OuterIterator_t>;
165 
167  using value_type = typename InnerIterator_t::value_type;
168 
169 
170  struct BeginPositionTag {};
171  struct EndPositionTag {};
172 
173  static constexpr BeginPositionTag begin = {};
174  static constexpr EndPositionTag end = {};
175 
181  deep_const_fwd_iterator_nested() = default;
182 
194 
211  template <class CONT>
213  deep_const_fwd_iterator_nested(std::begin(cont), std::end(cont))
214  { skip_empty(); }
215 
232  template <class CONT>
234  deep_const_fwd_iterator_nested(std::end(cont)) {}
235 
243  iterator_type& operator++();
244 
253  { iterator_type old(*this); this->operator++(); return old; }
254 
257  const value_type& operator*() const { return *inner_iter; }
258  const value_type& operator->() const { return *inner_iter; }
260 
264  bool operator== (const iterator_type& as) const
265  {
266  return (as.outer_iter == outer_iter)
267  && ((as.inner_iter == inner_iter) || (is_end() && as.is_end()));
268  }
270  bool operator!= (const iterator_type& as) const
271  {
272  return (as.outer_iter != outer_iter)
273  || ((as.inner_iter != inner_iter) && (!is_end() || !as.is_end()));
274  }
276 
277 
279 
283  operator bool() const { return !is_end(); }
284  bool operator! () const { return is_end(); }
286 
288  void swap(iterator_type& with);
289 
290  protected:
293 
296 
299  deep_const_fwd_iterator_nested(end, end) {}
300 
301  private:
302  void init_inner();
303  void reset_inner();
304  void skip_empty();
305 
306  bool is_end() const { return outer_iter == outer_end; }
307 
309  const typename InnerContainerExtractor_t::result_type&
310  extract_container(const typename OuterIterator_t::value_type& v)
311  { return InnerContainerExtractor_t()(v); }
312 
313  }; // class deep_const_fwd_iterator_nested<>
314 
315 
316  //---
317  //--- deep_const_fwd_iterator_nested implementation
318  //---
319 
320  template <typename ITER, typename INNERCONTEXTRACT>
324  outer_iter(src), outer_end(end)
325  {
326  if (is_end()) return;
327  init_inner();
328  skip_empty();
329  } // deep_const_fwd_iterator_nested(OuterIterator_t, OuterIterator_t)
330 
331 
332  template <typename ITER, typename INNERCONTEXTRACT>
335  ++inner_iter;
336  skip_empty();
337  return *this;
338  } // deep_const_fwd_iterator_nested<>::operator++()
339 
340 
341  template <typename ITER, typename INNERCONTEXTRACT>
344  {
345  std::swap(outer_iter, with.outer_iter);
346  std::swap(outer_end, with.outer_end);
347  std::swap(inner_iter, with.inner_iter);
348  std::swap(inner_end, with.inner_end);
349  } // deep_const_fwd_iterator_nested<>::swap()
350 
351 
352  template <typename ITER, typename INNERCONTEXTRACT>
354  inner_iter = std::begin(extract_container(*outer_iter));
355  inner_end = std::end(extract_container(*outer_iter));
356  } // deep_const_fwd_iterator_nested<>::init_inner()
357 
358 
359  template <typename ITER, typename INNERCONTEXTRACT>
361  { inner_end = inner_iter = {}; }
362 
363  template <typename ITER, typename INNERCONTEXTRACT>
365  while(inner_iter == inner_end) {
366  ++outer_iter;
367  if (is_end()) {
368  reset_inner();
369  return;
370  } // if
371  init_inner();
372  } // while inner iterator ended
373  } // skip_empty()
374 
375 
376 } // namespace lar
377 
378 
379 namespace std {
380  template <typename CITER, typename INNERCONTEXTRACT>
381  inline void swap(
384  )
385  { a.swap(b); }
386 } // namespace std
387 
388 
389 
390 #endif // NESTEDITERATOR_H
Float_t x
Definition: compare.C:6
deep_const_fwd_iterator_nested(const CONT &cont, EndPositionTag)
Constructor: starts from the end of the specified container.
typename InnerIterator_t::value_type value_type
Type of the value pointed by the iterator.
InnerIterator_t inner_iter
points to the current element
typename InnerContainer_t::const_iterator InnerIterator_t
const InnerContainerExtractor_t::result_type & extract_container(const typename OuterIterator_t::value_type &v)
Extracts the value out of the inner iterator.
STL namespace.
iterator_type operator++(int)
Postfix increment operator: points to the next element.
InnerIterator_t inner_end
stores the end of current inner container
OuterIterator_t outer_iter
points to current inner container
deep_const_fwd_iterator_nested(OuterIterator_t end)
Internal constructor: past-the-end iterator pointing to specified place.
iterator_type & operator++()
Prefix increment operator: points to the next element.
intermediate_table::const_iterator const_iterator
const value_type & operator*() const
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
void swap(iterator_type &with)
Swaps this with the specified iterator.
Functor returning the object specified as argument.
constexpr auto has_const_iterator_helper(T *=nullptr) -> decltype(typename T::const_iterator(), bool())
bool operator!=(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to different IDs.
LArSoft-specific namespace.
OuterIterator_t outer_end
points to past-the-end inner container
Internal helper class: actual implementation of nested iterator.
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
deep_const_fwd_iterator_nested(const CONT &cont, BeginPositionTag)
Constructor: starts from the beginning of the specified container.
const value_type & operator->() const
typename InnerContainerExtractor_t::result_type InnerContainer_t
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
T::second_type result_type
std::enable_if_t< std::is_base_of< art::SelectorBase, A >::value, art::NotHelper< A > > operator!(A const &a)
Definition: Selector.h:284
bool operator==(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to the same ID.
void skip_empty()
points to the next item