LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 <iterator> // std::forward_iterator_tag
16 #include <type_traits> // std::true_type, std::false_type, std::conditional
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>
41  T,
42  details::type_traits::has_const_iterator_helper((T*)(nullptr))> {};
43 
45  template <typename T>
46  class Identity;
47 
48  template <typename T>
49  class PairSecond;
50 
52  template <typename ITER, typename INNERCONTEXTRACT = Identity<typename ITER::value_type>>
54 
57  /* template <typename CITER>
58  using deep_fwd_const_iterator = std::conditional<
59  has_const_iterator<typename CITER::value_type>(),
60  deep_const_fwd_iterator_nested<CITER>,
61  CITER
62  >;
63 */
64 
65  template <typename CITER, typename INNERCONTEXTRACT = Identity<typename CITER::value_type>>
67 
68 } // namespace lar
69 
70 namespace std {
71  template <typename CITER, typename INNERCONTEXTRACT>
74 
75 } // namespace std
76 
77 //------------------------------------------------------------------------------
78 
79 namespace lar {
80 
81  namespace details {
82  namespace type_traits {
83 
84  //------------------------------------------------------------------------
85  // helpers for has_const_iterator() function
86  template <typename T, bool>
87  struct has_const_iterator_struct : public std::false_type {};
88 
89  template <typename T>
90  struct has_const_iterator_struct<T, true> : public std::true_type {};
91 
92  // Culled by SFINAE if T::const_iterator does not exist
93  // or is not accessible or not default-constructable
94  template <typename T>
95  constexpr auto has_const_iterator_helper(T* /* = nullptr */)
96  -> decltype(typename T::const_iterator(), bool())
97  {
98  return true;
99  }
100 
101  // Used as fallback when SFINAE culls the template method
102  constexpr bool has_const_iterator_helper(...)
103  {
104  return false;
105  }
106  //------------------------------------------------------------------------
107 
108  } // namespace type_traits
109  } // namespace details
110 
111  //---
112  //--- Identity declaration
113  //---
114  template <class T>
115  class Identity {
116  public:
117  typedef T argument_type;
118  typedef T result_type;
119 
120  result_type& operator()(argument_type& x) const { return x; }
121  const result_type& operator()(const argument_type& x) const { return x; }
122  }; // class Identity<>
123 
124  //---
125  //--- PairSecond declaration
126  //---
127  template <class T>
128  class PairSecond {
129  public:
130  typedef T argument_type;
131  typedef typename T::second_type result_type;
132 
133  result_type& operator()(argument_type& p) const { return p.second; }
134  const result_type& operator()(const argument_type& p) const { return p.second; }
135  }; // class PairSecond<>
136 
137  //---
138  //--- deep_const_fwd_iterator_nested declaration
139  //---
140  template <typename ITER, typename INNERCONTEXTRACT>
141  class deep_const_fwd_iterator_nested : public std::forward_iterator_tag {
142  public:
143  using OuterIterator_t = ITER;
144  using InnerContainerExtractor_t = INNERCONTEXTRACT;
145  using InnerContainer_t = typename InnerContainerExtractor_t::result_type;
146  using InnerIterator_t
147  // = deep_fwd_const_iterator<typename ITER::value_type::const_iterator>;
149 
150  // using iterator_type = deep_fwd_const_iterator<OuterIterator_t>;
151  using iterator_type =
153 
155  using value_type = typename InnerIterator_t::value_type;
156 
157  struct BeginPositionTag {};
158  struct EndPositionTag {};
159 
160  static constexpr BeginPositionTag begin = {};
161  static constexpr EndPositionTag end = {};
162 
168  deep_const_fwd_iterator_nested() = default;
169 
181 
198  template <class CONT>
200  : deep_const_fwd_iterator_nested(std::begin(cont), std::end(cont))
201  {
202  skip_empty();
203  }
204 
221  template <class CONT>
223  : deep_const_fwd_iterator_nested(std::end(cont))
224  {}
225 
233  iterator_type& operator++();
234 
243  {
244  iterator_type old(*this);
245  this->operator++();
246  return old;
247  }
248 
251  const value_type& operator*() const { return *inner_iter; }
252  const value_type& operator->() const { return *inner_iter; }
254 
258  bool operator==(const iterator_type& as) const
259  {
260  return (as.outer_iter == outer_iter) &&
261  ((as.inner_iter == inner_iter) || (is_end() && as.is_end()));
262  }
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 
272 
276  operator bool() const { return !is_end(); }
277  bool operator!() const { return is_end(); }
279 
281  void swap(iterator_type& with);
282 
283  protected:
286 
289 
292  {}
293 
294  private:
295  void init_inner();
296  void reset_inner();
297  void skip_empty();
298 
299  bool is_end() const { return outer_iter == outer_end; }
300 
302  const typename InnerContainerExtractor_t::result_type& extract_container(
303  const typename OuterIterator_t::value_type& v)
304  {
305  return InnerContainerExtractor_t()(v);
306  }
307 
308  }; // class deep_const_fwd_iterator_nested<>
309 
310  //---
311  //--- deep_const_fwd_iterator_nested implementation
312  //---
313 
314  template <typename ITER, typename INNERCONTEXTRACT>
316  OuterIterator_t src,
318  : outer_iter(src), outer_end(end)
319  {
320  if (is_end()) return;
321  init_inner();
322  skip_empty();
323  } // deep_const_fwd_iterator_nested(OuterIterator_t, OuterIterator_t)
324 
325  template <typename ITER, typename INNERCONTEXTRACT>
328  {
329  ++inner_iter;
330  skip_empty();
331  return *this;
332  } // deep_const_fwd_iterator_nested<>::operator++()
333 
334  template <typename ITER, typename INNERCONTEXTRACT>
336  {
337  std::swap(outer_iter, with.outer_iter);
338  std::swap(outer_end, with.outer_end);
339  std::swap(inner_iter, with.inner_iter);
340  std::swap(inner_end, with.inner_end);
341  } // deep_const_fwd_iterator_nested<>::swap()
342 
343  template <typename ITER, typename INNERCONTEXTRACT>
345  {
348  } // deep_const_fwd_iterator_nested<>::init_inner()
349 
350  template <typename ITER, typename INNERCONTEXTRACT>
352  {
353  inner_end = inner_iter = {};
354  }
355 
356  template <typename ITER, typename INNERCONTEXTRACT>
358  {
359  while (inner_iter == inner_end) {
360  ++outer_iter;
361  if (is_end()) {
362  reset_inner();
363  return;
364  } // if
365  init_inner();
366  } // while inner iterator ended
367  } // skip_empty()
368 
369 } // namespace lar
370 
371 namespace std {
372  template <typename CITER, typename INNERCONTEXTRACT>
375  {
376  a.swap(b);
377  }
378 } // namespace std
379 
380 #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.
deep_const_fwd_iterator_nested()=default
Default constructor: invalid iterator.
typename InnerIterator_t::value_type value_type
Type of the value pointed by the iterator.
InnerIterator_t inner_iter
points to the current element
result_type & operator()(argument_type &x) const
bool operator!() const
Bonus: convert to bool to find out if we are at the end.
result_type & operator()(argument_type &p) const
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.
const result_type & operator()(const argument_type &x) const
STL namespace.
iterator_type operator++(int)
Postfix increment operator: points to the next element.
intermediate_table::const_iterator const_iterator
const result_type & operator()(const argument_type &p) const
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.
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
iterator_type & operator++()
Prefix increment operator: points to the next element.
const value_type & operator*() const
bool operator!=(const iterator_type &as) const
Returns true if the two iterators are not equivalent.
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==(const iterator_type &as) const
Returns true if the two iterators are not equivalent.
LArSoft-specific namespace.
OuterIterator_t outer_end
points to past-the-end inner container
Internal helper class: actual implementation of nested iterator.
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
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
T::second_type result_type
void skip_empty()
points to the next item