VCCC  2024.05
VisualCamp Common C++ library
common_iterator.hpp
Go to the documentation of this file.
1 //
2 // Created by cosge on 2024-01-26.
3 //
4 
5 #ifndef VCCC_ITERATOR_COMMON_ITERATOR_HPP_
6 #define VCCC_ITERATOR_COMMON_ITERATOR_HPP_
7 
8 #include <new>
9 #include <type_traits>
10 #include <utility>
11 
40 #include "vccc/variant.hpp"
41 
42 namespace vccc {
43 
46 
47 template<typename I, typename S>
49  class proxy {
50  friend class common_iterator;
51 
52  iter_value_t<I> keep_;
53  constexpr proxy(iter_reference_t<I>&& x)
54  : keep_(std::forward<iter_reference_t<I>>(x)) {}
55 
56  public:
57  constexpr const iter_value_t<I>* operator->() const noexcept {
58  return vccc::addressof(keep_);
59  }
60 
61  };
62 
63  class postfix_proxy {
64  friend class common_iterator;
65 
66  iter_value_t<I> keep_;
67  constexpr postfix_proxy(iter_reference_t<I>&& x)
68  : keep_(std::forward<iter_reference_t<I>>(x)) {}
69 
70  public:
71  constexpr const iter_value_t<I>& operator*() const noexcept {
72  return keep_;
73  }
74  };
75 
76  public:
77  static_assert(input_or_output_iterator<I>::value, "Constraints not satisfied");
78  static_assert(sentinel_for<S, I>::value, "Constraints not satisfied");
79  static_assert(negation<same_as<I, S>>::value, "Constraints not satisfied");
80  static_assert(copyable<I>::value, "Constraints not satisfied");
81 
82  common_iterator() = default;
83 
84  constexpr common_iterator(I i) : var_(std::move(i)) {}
85  constexpr common_iterator(S s) : var_(std::move(s)) {}
86 
87  template<typename I2, typename S2, std::enable_if_t<conjunction<
90  >::value, int> = 0>
92  noexcept(conjunction<
93  std::is_nothrow_constructible<I, const I2&>,
94  std::is_nothrow_constructible<S, const S2&>>::value)
95  : var_{detail::variant_valueless_ctor{}}
96  {
97  switch (x.var_.index()) {
98  case 0:
99  var_.emplace<0>(detail::variant_raw_get(x.var_._base().storage(), in_place_index<0>));
100  break;
101  case 1:
102  var_.emplace<1>(detail::variant_raw_get(x.var_._base().storage(), in_place_index<1>));
103  break;
104  default:
105  break;
106  }
107  }
108 
109  template<typename I2, typename S2>
111  noexcept(conjunction<
112  std::is_nothrow_constructible<I, const I2&>, std::is_nothrow_assignable<I, const I2&>,
113  std::is_nothrow_constructible<S, const S2&>, std::is_nothrow_assignable<S, const S2&> >::value)
114  {
115  if (var_.index() == x.var_.index()) {
116  switch (x.var_.index()) {
117  case 0:
118  this->iterator() = detail::variant_raw_get(x.var_._base().storage(), in_place_index<0>);
119  return *this;
120  case 1:
121  this->sentinel() = detail::variant_raw_get(x.var_._base().storage(), in_place_index<1>);
122  return *this;
123  default:
124  break;
125  }
126  }
127 
128  switch (x.var_.index()) {
129  case 0:
130  var_.emplace<0>(detail::variant_raw_get(x._base().storage(), in_place_index<0>));
131  break;
132  case 1:
133  var_.emplace<1>(detail::variant_raw_get(x._base().storage(), in_place_index<1>));
134  break;
135  default:
136  break;
137  }
138 
139  return *this;
140  }
141 
142  constexpr decltype(auto) operator*() {
143  return *this->iterator();
144  }
145 
147  constexpr decltype(auto) operator*() const {
148  return *this->iterator();
149  }
150 
151  template<typename I2 = I, std::enable_if_t<conjunction<
153  disjunction<
154  std::is_pointer<I2>,
156  std::is_reference<iter_reference_t<I2>>,
158  >
159  >::value, int> = 0>
160  constexpr auto operator->() const {
161  using tag =
162  detail::conditional_tag<
164  std::is_reference<iter_reference_t<I>>
165  >;
166  return operator_arrow(tag{});
167  }
168 
170  ++this->iterator();
171  return *this;
172  }
173 
174  constexpr decltype(auto) operator++(int) {
175  using tag =
176  detail::conditional_tag<
178  disjunction<
179  conjunction<
180  detail::is_post_incrementable<I>,
182  >,
186  >
187  >;
188  return post_increment(tag{});
189  }
190 
191  template<typename I2, typename S2, std::enable_if_t<conjunction<
195  >::value, int> = 0>
196  friend constexpr bool operator==(const common_iterator& x, const common_iterator<I2, S2>& y) {
197  if (x.var_.index() == y.var_.index())
198  return true;
199 
200  using namespace vccc::rel_ops;
201  switch (x.var_.index()) {
202  case 0:
203  switch(y.var_.index()) {
204  case 0: return true;
205  case 1: return x.iterator() == y.sentinel();
206  default: return false;
207  }
208  case 1:
209  switch(y.var_.index()) {
210  case 0: return x.sentinel() == y.iterator();
211  case 1: return true;
212  default: return false;
213  }
214  default:
215  return false;
216  }
217  }
218 
219  template<typename I2, typename S2, std::enable_if_t<conjunction<
223  >::value, int> = 0>
224  friend constexpr bool operator!=(const common_iterator& x, const common_iterator<I2, S2>& y) {
225  return !(x == y);
226  }
227 
228  template<typename I2, typename S2, std::enable_if_t<conjunction<
232  >::value, int> = 0>
233  friend constexpr bool operator==(const common_iterator& x, const common_iterator<I2, S2>& y) {
234  using namespace vccc::rel_ops;
235  switch (x.var_.index()) {
236  case 0:
237  switch(y.var_.index()) {
238  case 0: return x.iterator() == y.iterator();
239  case 1: return x.iterator() == y.sentinel();
240  default: return false;
241  }
242  case 1:
243  switch(y.var_.index()) {
244  case 0: return x.sentinel() == y.iterator();
245  case 1: return true;
246  default: return false;
247  }
248  default:
249  return false;
250  }
251  }
252 
253  template<typename I2, typename S2, std::enable_if_t<conjunction<
257  >::value, int> = 0>
258  friend constexpr bool operator!=(const common_iterator& x, const common_iterator<I2, S2>& y) {
259  return !(x == y);
260  }
261 
262 
263  template<typename I2, typename S2, std::enable_if_t<conjunction<
267  >::value, int> = 0>
269  switch (x.var_.index()) {
270  case 0:
271  switch(y.var_.index()) {
272  case 0: return x.iterator() - y.iterator();
273  case 1: return x.iterator() - y.sentinel();
274  default: return 0;
275  }
276  case 1:
277  switch(y.var_.index()) {
278  case 0: return x.sentinel() - y.iterator();
279  case 1: return 0;
280  default: return 0;
281  }
282  default:
283  return 0;
284  }
285  }
286 
287  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
288  input_iterator<I>
289  >::value, int> = 0>
290  friend constexpr decltype(auto) iter_move(const common_iterator& i)
291  noexcept(noexcept(ranges::iter_move(std::declval<const I&>())))
292  {
293  return vccc::ranges::iter_move(i.iterator());
294  }
295 
296  template<typename I2, typename S2, std::enable_if_t<
298  ::value, int> = 0>
299  friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
300  noexcept(noexcept(ranges::iter_swap(std::declval<const I&>(), std::declval<const I2&>())))
301  {
302  ranges::iter_swap(x.iterator(), y.iterator());
303  }
304 
305  private:
306  decltype(auto) iterator() {
307  return detail::variant_raw_get(var_._base().storage(), in_place_index<0>);
308  }
309  decltype(auto) iterator() const {
310  return detail::variant_raw_get(var_._base().storage(), in_place_index<0>);
311  }
312  decltype(auto) sentinel() {
313  return detail::variant_raw_get(var_._base().storage(), in_place_index<1>);
314  }
315  decltype(auto) sentinel() const {
316  return detail::variant_raw_get(var_._base().storage(), in_place_index<1>);
317  }
318 
319  constexpr auto operator_arrow(detail::tag_1) const {
320  return this->iterator();
321  }
322  constexpr auto operator_arrow(detail::tag_2) const {
323  auto&& tmp = **this;
324  return vccc::addressof(tmp);
325  }
326  constexpr auto operator_arrow(detail::tag_else) const {
327  return proxy(**this);
328  }
329 
330  constexpr decltype(auto) post_increment(detail::tag_1) {
331  auto tmp = *this;
332  ++*this;
333  return tmp;
334  }
335  constexpr decltype(auto) post_increment(detail::tag_2) {
336  return this->iterator()++;
337  }
338  constexpr postfix_proxy post_increment(detail::tag_else) {
339  postfix_proxy p(**this);
340  ++*this;
341  return p;
342  }
343 
344  variant<I, S> var_{};
345 };
346 
347 template<typename I, typename S>
350 };
351 
352 namespace detail {
353 
354 template<typename I, bool = std::is_integral<iter_difference_t<I>>::value /* false */>
355 struct common_iterator_category {
356 #if __cplusplus < 202002L
357  using iterator_category = iterator_ignore;
358 #endif
359 };
360 
361 template<typename I, bool v = has_typename_iterator_category<cxx20_iterator_traits<I>>::value /* false */>
362 struct common_iterator_category_check_forward : std::false_type {};
363 template<typename I>
364 struct common_iterator_category_check_forward<I, true>
365  : derived_from<typename cxx20_iterator_traits<I>::iterator_category, forward_iterator_tag> {};
366 
367 template<typename I>
368 struct common_iterator_category<I, true> {
369  using iterator_category =
370  std::conditional_t<
374  >;
375 };
376 
377 template<typename I, typename S, bool = has_operator_arrow<const common_iterator<I, S>&>::value /* false */>
378 struct common_iterator_pointer {
379  using type = void;
380 };
381 template<typename I, typename S>
382 struct common_iterator_pointer<I, S, true> {
383  using type = decltype(std::declval<const common_iterator<I, S>&>().operator->());
384 };
385 
386 } // namespace detail
387 
388 template<typename I, typename S>
389 struct cxx20_iterator_traits<common_iterator<I, S>> : detail::common_iterator_category<I> {
393  using pointer = typename detail::common_iterator_pointer<I, S>::type;
395 };
396 
397 template<typename I, typename S>
398 struct detail::is_primary_iterator_traits< cxx20_iterator_traits<common_iterator<I, S>> > : std::false_type {};
399 
401 
402 } // namespace vccc
403 
404 template<typename I, typename S>
405 struct std::iterator_traits<::vccc::common_iterator<I, S>>
406  : ::vccc::cxx20_iterator_traits<::vccc::common_iterator<I, S>> {};
407 
408 #endif // VCCC_ITERATOR_COMMON_ITERATOR_HPP_
Definition: common_iterator.hpp:48
constexpr friend void iter_swap(const common_iterator &x, const common_iterator< I2, S2 > &y) noexcept(noexcept(ranges::iter_swap(std::declval< const I & >(), std::declval< const I2 & >())))
Definition: common_iterator.hpp:299
constexpr decltype(auto) friend iter_move(const common_iterator &i) noexcept(noexcept(ranges::iter_move(std::declval< const I & >())))
Definition: common_iterator.hpp:290
constexpr decltype(auto) operator*()
Definition: common_iterator.hpp:142
constexpr common_iterator(S s)
Definition: common_iterator.hpp:85
constexpr friend iter_difference_t< I2 > operator-(const common_iterator &x, const common_iterator< I2, S2 > &y)
Definition: common_iterator.hpp:268
constexpr friend bool operator!=(const common_iterator &x, const common_iterator< I2, S2 > &y)
Definition: common_iterator.hpp:224
constexpr common_iterator(const common_iterator< I2, S2 > &x) noexcept(conjunction< std::is_nothrow_constructible< I, const I2 & >, std::is_nothrow_constructible< S, const S2 & >>::value)
Definition: common_iterator.hpp:91
constexpr friend bool operator==(const common_iterator &x, const common_iterator< I2, S2 > &y)
Definition: common_iterator.hpp:196
constexpr auto operator->() const
Definition: common_iterator.hpp:160
constexpr common_iterator(I i)
Definition: common_iterator.hpp:84
constexpr common_iterator & operator++()
Definition: common_iterator.hpp:169
constexpr common_iterator & operator=(const common_iterator< I2, S2 > &x) noexcept(conjunction< std::is_nothrow_constructible< I, const I2 & >, std::is_nothrow_assignable< I, const I2 & >, std::is_nothrow_constructible< S, const S2 & >, std::is_nothrow_assignable< S, const S2 & > >::value)
Definition: common_iterator.hpp:110
constexpr std::size_t index() const noexcept
Definition: variant.hpp:662
VCCC_CONSTEXPR_AFTER_CXX20 T & emplace(Args &&... args)
Definition: variant.hpp:674
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
std::forward_iterator_tag forward_iterator_tag
Definition: iterator_tag.hpp:17
typename iter_reference< T >::type iter_reference_t
Definition: iter_reference_t.hpp:30
typename iter_value< T >::type iter_value_t
Definition: iter_value_t.hpp:42
typename iter_difference< T >::type iter_difference_t
Computes the difference type of T
Definition: iter_difference_t.hpp:49
std::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
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: conjunction.hpp:22
specifies that a variable of the type can be constructed from or bound to a set of argument types
Definition: constructible_from.hpp:31
Models std::convertible_to
Definition: convertible_to.hpp:38
specifies that an object of a type can be copied, moved, and swapped
Definition: copyable.hpp:59
std::conditional_t< forward_iterator< I >::value, forward_iterator_tag, input_iterator_tag > iterator_concept
Definition: common_iterator.hpp:390
typename detail::common_iterator_pointer< I, S >::type pointer
Definition: common_iterator.hpp:393
iter_value_t< I > value_type
Definition: common_iterator.hpp:391
iter_reference_t< I > reference
Definition: common_iterator.hpp:394
iter_difference_t< I > difference_type
Definition: common_iterator.hpp:392
Definition: cxx20_iterator_traits.hpp:188
specifies that an object of a type can be dereferenced
Definition: dereferenceable.hpp:45
Definition: disjunction.hpp:22
specifies that operator == is an equivalence relation
Definition: equality_comparable.hpp:79
specifies that an input_iterator is a forward iterator, supporting equality comparison and multi-pass
Definition: forward_iterator.hpp:53
Definition: has_operator_arrow.hpp:18
iter_difference_t< I > difference_type
Definition: common_iterator.hpp:349
computes the difference type of a weakly_incrementable type
Definition: incrementable_traits.hpp:123
Definition: indirectly_readable.hpp:59
Definition: indirectly_swappable.hpp:46
specifies that objects of a type can be incremented and dereferenced
Definition: input_or_output_iterator.hpp:43
Definition: iterator_tag.hpp:28
Definition: negation.hpp:23
Models std::same_as
Definition: same_as.hpp:33
Definition: sentinel_for.hpp:24
specifies that the - operator can be applied to an iterator and a sentinel to calculate their differe...
Definition: sized_sentinel_for.hpp:75