Ookii.CommandLine for C++  2.0.0
range_helper.h
Go to the documentation of this file.
1 #ifndef OOKII_RANGE_HELPER_H_
4 #define OOKII_RANGE_HELPER_H_
5 
6 #pragma once
7 
8 #include <iterator>
9 
10 namespace ookii::details
11 {
12  // This is similar to a combination of the filter and transform views in C++20, but those are
13  // not used because they don't work in clang.
14  template<typename T, typename IteratorType>
15  class range_filter
16  {
17  using filter_function_type = std::function<bool(const typename IteratorType::reference)>;
18  using transform_function_type = std::function<T(const typename IteratorType::reference)>;
19 
20  class iterator
21  {
22  public:
23  using iterator_concept = std::forward_iterator_tag;
24  using value_type = T;
25  using difference_type = typename IteratorType::difference_type;
26  using pointer = std::remove_reference_t<value_type>*;
27  using reference = value_type&;
28 
29  iterator(IteratorType it, IteratorType end, filter_function_type filter, transform_function_type transform)
30  : _current{it},
31  _end{end},
32  _filter{filter},
33  _transform{transform}
34  {
35  next_value(true);
36  }
37 
38  iterator &operator++()
39  {
40  next_value(false);
41  return *this;
42  }
43 
44  iterator operator++(int)
45  {
46  iterator temp = *this;
47  next_value(false);
48  return temp;
49  }
50 
51  value_type operator*() const noexcept
52  {
53  return _transform(*_current);
54  }
55 
56  bool operator==(const iterator &other) const noexcept
57  {
58  return _current == other._current;
59  }
60 
61  private:
62  void next_value(bool check_current)
63  {
64  if (_current == _end || (check_current && (!_filter || _filter(*_current))))
65  {
66  return;
67  }
68 
69  do
70  {
71  ++_current;
72 
73  } while (_current != _end && _filter && !_filter(*_current));
74  }
75 
76  IteratorType _current;
77  IteratorType _end;
78  filter_function_type _filter;
79  transform_function_type _transform;
80  };
81 
82  public:
83  range_filter(IteratorType begin, IteratorType end, transform_function_type transform,
84  filter_function_type filter = {})
85  : _begin{begin},
86  _end{end},
87  _transform{transform},
88  _filter{filter}
89  {
90  }
91 
92  iterator begin() const noexcept
93  {
94  return iterator{_begin, _end, _filter, _transform};
95  }
96 
97  iterator end() const noexcept
98  {
99  return iterator{_end, _end, _filter, _transform};
100  }
101 
102  private:
103  IteratorType _begin;
104  IteratorType _end;
105  transform_function_type _transform;
106  filter_function_type _filter;
107  };
108 }
109 
110 #endif