VCCC  2024.05
VisualCamp Common C++ library
counted_iterator.hpp
Go to the documentation of this file.
1 //
2 // Created by cosge on 2024-01-03.
3 //
4 
5 #ifndef VCCC_ITERATOR_COUNTED_ITERATOR_HPP
6 #define VCCC_ITERATOR_COUNTED_ITERATOR_HPP
7 
8 #include <iterator>
9 #include <type_traits>
10 #include <utility>
11 
36 
37 namespace vccc {
38 namespace detail {
39 
41 struct counted_iterator_value_type {
42  using value_type = iter_value_t<I>;
43 };
44 template<typename I>
45 struct counted_iterator_value_type<I, false> {};
46 
47 template<typename I, typename = void>
48 struct counted_iterator_iterator_concept {};
49 template<typename I>
50 struct counted_iterator_iterator_concept<I, void_t<typename I::iterator_concept>> {
51  using iterator_concept = typename I::iterator_concept;
52 };
53 
54 template<typename I, typename = void>
55 struct counted_iterator_iterator_category {};
56 template<typename I>
57 struct counted_iterator_iterator_category<I, void_t<typename I::iterator_category>> {
58  using iterator_category = typename I::iterator_category;
59 };
60 
61 } // namespace detail
62 
65 
66 template<typename I>
68  : public detail::counted_iterator_value_type<I>
69  , public detail::counted_iterator_iterator_concept<I>
70  , public detail::counted_iterator_iterator_category<I>
71 {
72  public:
73  static_assert(input_or_output_iterator<I>::value, "Constraints not satisfied");
74 
75  using iterator_type = I;
77 
78  constexpr counted_iterator() = default;
79 
81  : current_(std::move(x)), length_(n) {}
82 
84  constexpr counted_iterator(const counted_iterator<I2>& other)
85  : current_(other.current_), length_(other.length_) {}
86 
87 
89  constexpr counted_iterator& operator=(const counted_iterator<I2>& other) {
90  current_ = other.current_;
91  length_ = other.length_;
92  return *this;
93  }
94 
95 
96  constexpr const I& base() const& noexcept {
97  return current_;
98  }
99  constexpr I base() && {
100  return std::move(current_);
101  }
102 
103 
104  constexpr difference_type count() const noexcept {
105  return length_;
106  }
107 
108 
109  constexpr decltype(auto) operator*() {
110  return *current_;
111  }
113  constexpr decltype(auto) operator*() const {
114  return *current_;
115  }
117  constexpr auto operator->() const noexcept {
118  return vccc::to_address(current_);
119  }
120 
121 
123  constexpr decltype(auto) operator[](iter_difference_t<I> n) const {
124  return this->base()[n];
125  }
126 
127 
129  ++current_;
130  --length_;
131  return *this;
132 
133  }
135  VCCC_CONSTEXPR_AFTER_CXX20 decltype(auto) operator++(int) {
136  --length_;
137  try {
138  return current_++;
139  } catch (...) {
140  ++length_;
141  throw;
142  }
143  }
145  constexpr counted_iterator operator++(int) {
146  counted_iterator temp{*this};
147  ++*this;
148  return temp;
149  }
152  --current_;
153  ++length_;
154  return *this;
155  }
157  constexpr counted_iterator operator--(int) {
158  counted_iterator temp{*this};
159  --*this;
160  return temp;
161  }
162 
165  return counted_iterator(current_ + n, length_ - n);
166  }
169  current_ += n;
170  length_ -= n;
171  return *this;
172  }
173 
176  return counted_iterator(current_ - n, length_ + n);
177  }
180  current_ -= n;
181  length_ += n;
182  return *this;
183  }
184 
186  friend constexpr bool operator==(const counted_iterator& x, const counted_iterator<I2>& y) {
187  using namespace vccc::rel_ops;
188  return x.count() == y.count();
189  }
190 
192  friend constexpr bool operator<(const counted_iterator& x, const counted_iterator<I2>& y) {
193  using namespace vccc::rel_ops;
194  return y.count() < x.count();
195  }
196 
198  friend constexpr bool operator!=(const counted_iterator& x, const counted_iterator<I2>& y) {
199  using namespace vccc::rel_ops;
200  return x.count() != y.count();
201  }
203  friend constexpr bool operator<=(const counted_iterator& x, const counted_iterator<I2>& y) {
204  using namespace vccc::rel_ops;
205  return y.count() <= x.count();
206  }
208  friend constexpr bool operator>(const counted_iterator& x, const counted_iterator<I2>& y) {
209  using namespace vccc::rel_ops;
210  return y.count() > x.count();
211  }
213  friend constexpr bool operator>=(const counted_iterator& x, const counted_iterator<I2>& y) {
214  using namespace vccc::rel_ops;
215  return y.count() >= x.count();
216  }
217 
218 
219  friend constexpr bool operator==(const counted_iterator& x, default_sentinel_t) {
220  return x.count() == 0;
221  }
222  friend constexpr bool operator==(default_sentinel_t, const counted_iterator& x) {
223  return x.count() == 0;
224  }
225  friend constexpr bool operator!=(const counted_iterator& x, default_sentinel_t) {
226  return x.count() != 0;
227  }
228  friend constexpr bool operator!=(default_sentinel_t, const counted_iterator& x) {
229  return x.count() != 0;
230  }
231 
232 
233  template<typename I2 = I>
236  return x + n;
237  }
238 
239  template<typename I2>
240  friend constexpr iter_difference_t<I2>
242  return y.count() - x.count();
243  }
244 
245  friend constexpr iter_difference_t<I>
247  return -x.count();
248  }
249 
250  friend constexpr iter_difference_t<I>
252  return y.count();
253  }
254 
256  friend constexpr iter_rvalue_reference_t<I2>
257  iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.base()))) {
258  return ranges::iter_move(i.base());
259  }
260 
262  friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y)
263  noexcept(noexcept(ranges::iter_swap(x.base(), y.base())))
264  {
265  VCCC_DEBUG_ASSERT(x.count() != 0 && y.count() != 0);
266  ranges::iter_swap(x.base(), y.base());
267  }
268 
269  private:
270  iterator_type current_;
271  difference_type length_ = 0;
272 };
273 
274 namespace detail {
275 
276 template<typename I, bool = is_primary_iterator_traits<cxx20_iterator_traits<I>>::value /* true */>
277 struct counted_iterator_iterator_traits : cxx20_iterator_traits_sfinae<counted_iterator<I>> {};
278 
279 template<typename I>
280 struct counted_iterator_iterator_traits<I, false> : cxx20_iterator_traits<I> {
281  using pointer = std::conditional_t<
283  std::add_pointer_t<iter_reference_t<I>>,
284  void
285  >;
286 };
287 
288 template<typename I>
289 struct is_primary_iterator_traits<std::iterator_traits<counted_iterator<I>>>
290  : is_primary_iterator_traits<cxx20_iterator_traits<I>> {};
291 
292 template<typename I>
293 struct is_primary_iterator_traits<cxx20_iterator_traits<counted_iterator<I>>>
294  : is_primary_iterator_traits<cxx20_iterator_traits<I>> {};
295 
296 } // namespace detail
297 
298 
299 template<typename I>
300 struct cxx20_iterator_traits<counted_iterator<I>> : detail::counted_iterator_iterator_traits<I> {
301  static_assert(input_iterator<I>::value, "Constraints not satisfied");
302 };
303 
304 
305 
307 
308 } // namespace vccc
309 
310 #if __cplusplus >= 202002L
311 
312 namespace std {
313 
314 // TODO: Use base class of std::iterator_traits<T>
315 
316 template<::std::input_iterator I>
318 struct iterator_traits<vccc::counted_iterator<I>> : iterator_traits<I> {
319  using pointer = typename vccc::cxx20_iterator_traits<vccc::counted_iterator<I>>::pointer;
320 };
321 
322 } // namespace std
323 
324 #endif
325 
326 #endif // VCCC_ITERATOR_COUNTED_ITERATOR_HPP
Definition: counted_iterator.hpp:71
constexpr difference_type count() const noexcept
Definition: counted_iterator.hpp:104
I iterator_type
Definition: counted_iterator.hpp:75
constexpr friend iter_difference_t< I > operator-(const counted_iterator &x, default_sentinel_t)
Definition: counted_iterator.hpp:246
constexpr friend bool operator>(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:208
constexpr counted_iterator()=default
constexpr counted_iterator & operator-=(iter_difference_t< I > n)
Definition: counted_iterator.hpp:179
constexpr counted_iterator operator++(int)
Definition: counted_iterator.hpp:145
constexpr auto operator->() const noexcept
Definition: counted_iterator.hpp:117
constexpr counted_iterator operator-(iter_difference_t< I > n) const
Definition: counted_iterator.hpp:175
constexpr friend iter_rvalue_reference_t< I2 > iter_move(const counted_iterator &i) noexcept(noexcept(ranges::iter_move(i.base())))
Definition: counted_iterator.hpp:257
constexpr friend iter_difference_t< I > operator-(default_sentinel_t, const counted_iterator &y)
Definition: counted_iterator.hpp:251
constexpr counted_iterator & operator=(const counted_iterator< I2 > &other)
Definition: counted_iterator.hpp:89
constexpr friend void iter_swap(const counted_iterator &x, const counted_iterator< I2 > &y) noexcept(noexcept(ranges::iter_swap(x.base(), y.base())))
Definition: counted_iterator.hpp:262
constexpr counted_iterator operator+(iter_difference_t< I > n) const
Definition: counted_iterator.hpp:164
iter_difference_t< I > difference_type
Definition: counted_iterator.hpp:76
constexpr friend bool operator==(default_sentinel_t, const counted_iterator &x)
Definition: counted_iterator.hpp:222
constexpr friend iter_difference_t< I2 > operator-(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:241
constexpr friend bool operator<(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:192
constexpr counted_iterator & operator+=(iter_difference_t< I > n)
Definition: counted_iterator.hpp:168
constexpr friend bool operator>=(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:213
constexpr friend bool operator==(const counted_iterator &x, default_sentinel_t)
Definition: counted_iterator.hpp:219
constexpr counted_iterator & operator--()
Definition: counted_iterator.hpp:151
constexpr counted_iterator(const counted_iterator< I2 > &other)
Definition: counted_iterator.hpp:84
constexpr friend std::enable_if_t< random_access_iterator< I2 >::value, counted_iterator > operator+(iter_difference_t< I > n, const counted_iterator &x)
Definition: counted_iterator.hpp:235
constexpr friend bool operator!=(default_sentinel_t, const counted_iterator &x)
Definition: counted_iterator.hpp:228
constexpr I base() &&
Definition: counted_iterator.hpp:99
constexpr friend bool operator<=(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:203
constexpr counted_iterator(I x, iter_difference_t< I > n)
Definition: counted_iterator.hpp:80
constexpr counted_iterator & operator++()
Definition: counted_iterator.hpp:128
constexpr const I & base() const &noexcept
Definition: counted_iterator.hpp:96
constexpr counted_iterator operator--(int)
Definition: counted_iterator.hpp:157
constexpr friend bool operator!=(const counted_iterator &x, default_sentinel_t)
Definition: counted_iterator.hpp:225
constexpr friend bool operator!=(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:198
constexpr friend bool operator==(const counted_iterator &x, const counted_iterator< I2 > &y)
Definition: counted_iterator.hpp:186
#define VCCC_CONSTEXPR_AFTER_CXX20
Definition: constexpr.hpp:26
#define VCCC_DEBUG_ASSERT(expr)
Definition: debug_assert.hpp:19
constexpr VCCC_INLINE_OR_STATIC detail_iter_move::iter_move_niebloid iter_move
Definition: iter_move.hpp:92
constexpr VCCC_INLINE_OR_STATIC detail_iter_swap::iter_swap_niebloid iter_swap
Definition: iter_swap.hpp:90
constexpr T * to_address(T *p) noexcept
Definition: to_address.hpp:37
typename iter_rvalue_reference< T >::type iter_rvalue_reference_t
Definition: iter_rvalue_reference_t.hpp:33
typename iter_difference< T >::type iter_difference_t
Computes the difference type of T
Definition: iter_difference_t.hpp:49
void void_t
Definition: void_t.hpp:19
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: cxx20_iterator_traits.hpp:188
Definition: default_sentinel_t.hpp:23
specifies that a type is an input iterator, that is, its referenced values can be read and it can be ...
Definition: input_iterator.hpp:55
specifies that objects of a type can be incremented and dereferenced
Definition: input_or_output_iterator.hpp:43