VCCC  2024.05
VisualCamp Common C++ library
iota_view.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2023/12/26.
3 //
4 
5 #ifndef VCCC_RANGES_VIEWS_IOTA_HPP_
6 #define VCCC_RANGES_VIEWS_IOTA_HPP_
7 
8 #include <cstdint>
9 #include <type_traits>
10 
11 #include "vccc/core.hpp"
34 
35 namespace vccc {
36 namespace ranges {
37 namespace detail {
38 
39 template<typename I>
40 struct iota_diff
41  : std::conditional_t<
42  disjunction<
43  negation<std::is_integral<I>>,
44  conjunction<
45  std::is_integral<I>,
46  bool_constant<( sizeof(iter_difference_t<I>) > sizeof(I) )>
47  >
48  >::value,
49  type_identity<iter_difference_t<I>>,
50  type_identity<std::intmax_t>
51  > {};
52 
53 template<typename I>
54 using iota_diff_t = typename iota_diff<I>::type;
55 
56 template<typename I, bool = incrementable<I>::value, typename = void, typename = void>
57 struct iv_decrementable : std::false_type {};
58 
59 template<typename I>
60 struct iv_decrementable<
61  I, true,
62  void_t<decltype( --std::declval<I&>() )>,
63  void_t<decltype( std::declval<I&>()-- )>
64  > : conjunction<
65  same_as<decltype( --std::declval<I&>() ), I&>,
66  same_as<decltype( std::declval<I&>()-- ), I>
67  > {};
68 
69 template<typename I, typename D, typename = void, typename = void, typename = void, typename = void>
70 struct iv_advanceable_explicit : std::false_type {};
71 
72 template<typename I, typename D>
73 struct iv_advanceable_explicit<
74  I, D,
75  void_t<decltype( std::declval<I>() + std::declval<D>() )>,
76  void_t<decltype( std::declval<D>() + std::declval<I>() )>,
77  void_t<decltype( std::declval<I>() - std::declval<D>() )>,
78  void_t<decltype( std::declval<I>() - std::declval<I>() )>
79  > : conjunction<
80  std::is_constructible<remove_cvref_t<I>, decltype( std::declval<I>() + std::declval<D>() )>,
81  std::is_constructible<remove_cvref_t<I>, decltype( std::declval<D>() + std::declval<I>() )>,
82  std::is_constructible<remove_cvref_t<I>, decltype( std::declval<I>() - std::declval<D>() )>,
83  convertible_to<decltype( std::declval<I>() - std::declval<I>() ), remove_cvref_t<D>>
84  >{};
85 
86 template<typename I, bool = conjunction<iv_decrementable<I>, totally_ordered<I>>::value>
87 struct iv_advanceable : std::false_type {};
88 
89 // TODO: Implement
90 template<typename I>
91 struct iv_advanceable<I, true>
92  : conjunction<
93  implicit_expression_check<vccc::detail::detail_random_access_iterator::explicit_op_assign_check, I&, const iota_diff_t<I>&>,
94  implicit_expression_check<iv_advanceable_explicit, const I&, const iota_diff_t<I>&>
95  > {};
96 
98 struct iota_view_iterator_category {
99  using iterator_category = input_iterator_tag;
100 };
101 template<typename I>
102 struct iota_view_iterator_category<I, false> {};
103 
104 template<typename I>
105 struct iota_view_iterator_concept
106  : std::conditional_t<
107  iv_advanceable<I>::value, type_identity<random_access_iterator_tag>,
108  std::conditional_t<
109  iv_decrementable<I>::value, type_identity<bidirectional_iterator_tag>,
110  std::conditional_t<
111  incrementable<I>::value, type_identity<forward_iterator_tag>,
112  type_identity<input_iterator_tag>
113  >>> {};
114 
115 template<typename W, typename Bound, typename IV>
116 struct iv_ctor_iterator_last {
117  using type = typename IV::sentinel;
118 };
119 
120 template<typename W, typename IV>
121 struct iv_ctor_iterator_last<W, unreachable_sentinel_t, IV> {
122  using type = unreachable_sentinel_t;
123 };
124 
125 template<typename W, typename IV>
126 struct iv_ctor_iterator_last<W, W, IV> {
127  using type = typename IV::iterator;
128 };
129 
130 } // namespace detail
131 
195 template<typename W,
196  typename Bound = unreachable_sentinel_t>
197 class iota_view : public view_interface<iota_view<W, Bound>> {
198  public:
199  static_assert(weakly_incrementable<W>::value, "Constraint not satisfied");
200  static_assert(semiregular<Bound>::value, "Constraint not satisfied");
201  static_assert(weakly_equality_comparable_with<W, Bound>::value, "Constraint not satisfied");
202  static_assert(copyable<W>::value, "Constraint not satisfied");
203 
204  class iterator;
205  class sentinel;
206 
207  class iterator : public detail::iota_view_iterator_category<W> {
208  public:
209  using value_type = W;
210  using difference_type = detail::iota_diff_t<W>;
211  using iterator_concept = typename detail::iota_view_iterator_concept<W>::type;
212 
213  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
214  default_initializable<W>
215  >::value, int> = 0>
216  constexpr iterator() : value_(W()) {}
217 
218  constexpr explicit iterator(W value) : value_(value) {}
219 
220  constexpr W operator*() const noexcept(std::is_nothrow_copy_constructible<W>::value) {
221  return value_;
222  }
223 
224  constexpr iterator& operator++() {
225  ++value_;
226  return *this;
227  }
228 
229  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
230  negation<incrementable<W>>
231  >::value, int> = 0>
232  constexpr void operator++(int) {
233  ++value_;
234  }
235  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
236  incrementable<W>
237  >::value, int> = 0>
238  constexpr iterator operator++(int) {
239  iterator tmp = *this;
240  ++value_;
241  return tmp;
242  }
243 
244 
245  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
246  detail::iv_decrementable<W>
247  >::value, int> = 0>
248  constexpr iterator& operator--() {
249  --value_;
250  return *this;
251  }
252  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
253  detail::iv_decrementable<W>
254  >::value, int> = 0>
255  constexpr iterator operator--(int) {
256  iterator tmp = *this;
257  --value_;
258  return tmp;
259  }
260 
261  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
262  detail::iv_advanceable<W>,
263  is_unsigned_integer_like<W>
264  >::value, int> = 0>
266  n < 0 ? (void)(value_ += static_cast<W>(n)) : (void)(value_ -= static_cast<W>(-n));
267  return *this;
268  }
269  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
270  detail::iv_advanceable<W>,
271  negation<is_unsigned_integer_like<W>>
272  >::value, int> = 0>
274  value_ += static_cast<W>(n);
275  return *this;
276  }
277 
278  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
279  detail::iv_advanceable<W>,
280  is_unsigned_integer_like<W>
281  >::value, int> = 0>
283  n < 0 ? (void)(value_ -= static_cast<W>(n)) : (void)(value_ += static_cast<W>(-n));
284  return *this;
285  }
286  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
287  detail::iv_advanceable<W>,
288  negation<is_unsigned_integer_like<W>>
289  >::value, int> = 0>
291  value_ -= n;
292  return *this;
293  }
294 
295  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
296  detail::iv_advanceable<W>
297  >::value, int> = 0>
298  constexpr W operator[](difference_type n) const {
299  return W(value_ + n);
300  }
301 
302  friend constexpr std::enable_if_t<equality_comparable<W>::value, bool>
303  operator==(const iterator& x, const iterator& y) {
304  return x.value_ == y.value_;
305  }
306  friend constexpr std::enable_if_t<equality_comparable<W>::value, bool>
307  operator!=(const iterator& x, const iterator& y) {
308  return !(x == y);
309  }
311  operator<(const iterator& x, const iterator& y) {
312  return x.value_ < y.value_;
313  }
314  friend constexpr std::enable_if_t<totally_ordered<W>::value, bool>
315  operator>(const iterator& x, const iterator& y) {
316  return y < x;
317  }
319  operator<=(const iterator& x, const iterator& y) {
320  return !(y < x);
321  }
322  friend constexpr std::enable_if_t<totally_ordered<W>::value, bool>
323  operator>=(const iterator& x, const iterator& y) {
324  return !(x < y);
325  }
326 
329  i += n;
330  return i;
331  }
334  i += n;
335  return i;
336  }
337 
340  i -= n;
341  return i;
342  }
343 
344 
345  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
346  detail::iv_advanceable<W>,
347  is_signed_integer_like<W>
348  >::value, int> = 0>
349  friend constexpr difference_type operator-(iterator x, iterator y) {
350  return difference_type(difference_type(x.value_) - difference_type(y.value_));
351  }
352 
353  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
354  detail::iv_advanceable<W>,
355  negation<is_signed_integer_like<W>>,
356  is_unsigned_integer_like<W>
357  >::value, int> = 0>
358  friend constexpr difference_type operator-(iterator x, iterator y) {
359  using D = difference_type;
360  return y.value_ > x.value_ ? D(-D(y.value_ - x.value_)) : D(x.value_ - y.value_);
361  }
362 
363  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
364  detail::iv_advanceable<W>,
365  negation<is_signed_integer_like<W>>,
366  negation<is_unsigned_integer_like<W>>
367  >::value, int> = 0>
368  friend constexpr difference_type operator-(iterator x, iterator y) {
369  return x.value_ - y.value_;
370  }
371 
372  private:
373  friend class iota_view;
374  friend class sentinel;
375 
376  W value_;
377  };
378 
379  class sentinel {
380  public:
381  constexpr sentinel() : bound_(Bound()) {}
382 
383  constexpr explicit sentinel(Bound bound) : bound_(bound) {}
384 
385  friend constexpr bool operator==(const iterator& x, const sentinel& y) {
386  using namespace vccc::rel_ops;
387  return *x == y.bound_;
388  }
389  friend constexpr bool operator!=(const iterator& x, const sentinel& y) {
390  return !(x == y);
391  }
392  friend constexpr bool operator==(const sentinel& y, const iterator& x) {
393  return x == y;
394  }
395  friend constexpr bool operator!=(const sentinel& y, const iterator& x) {
396  return !(x == y);
397  }
398 
399  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
400  sized_sentinel_for<Bound, W>
401  >::value, int> = 0>
402  friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y) {
403  return *x - y.bound_;
404  }
405 
406  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
407  sized_sentinel_for<Bound, W>
408  >::value, int> = 0>
409  friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y) {
410  return -(*y - x.bound_);
411  }
412 
413  private:
414  friend class iota_view;
415 
416  Bound bound_;
417  };
418 
419 
420  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
421  default_initializable<W>
422  >::value, int> = 0>
423  constexpr iota_view() : value_(W()), bound_(Bound()) {}
424 
425  constexpr explicit iota_view(W value) : value_(value), bound_(Bound()) {}
426 
427  constexpr explicit iota_view(type_identity_t<W> value,
428  type_identity_t<Bound> bound) : value_(value), bound_(bound) {}
429 
430  constexpr explicit iota_view(iterator first, typename detail::iv_ctor_iterator_last<W, Bound, iota_view>::type last)
431  : value_(*first), bound_(get_value(last)) {}
432 
433  constexpr iterator begin() const {
434  return iterator(value_);
435  }
436 
437 
438  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
439  negation<same_as<W, Bound>>
440  >::value, int> = 0>
441  constexpr sentinel end() const {
442  return sentinel(bound_);
443  }
444  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
445  same_as<W, Bound>
446  >::value, int> = 0>
447  constexpr iterator end() const {
448  return iterator(bound_);
449  }
450 
451  constexpr bool empty() const {
452  using namespace vccc::rel_ops;
453  return value_ == bound_;
454  }
455 
456  template<typename Dummy = void, std::enable_if_t<conjunction<std::is_void<Dummy>,
457  disjunction<
458  conjunction<same_as<W, Bound>, detail::iv_advanceable<W>>,
459  conjunction<is_integer_like<W>, is_integer_like<Bound>>,
460  sized_sentinel_for<Bound, W>
461  >
462  >::value, int> = 0>
463  constexpr auto size() const {
465  }
466 
467  private:
468  template<typename T>
469  static constexpr auto to_unsigned_like(T x) {
470  using R = std::make_unsigned_t<T>;
471  return static_cast<R>(x);
472  }
473 
474  constexpr auto size_impl(std::true_type) const {
475  return (value_ < 0)
476  ? ((bound_ < 0)
477  ? to_unsigned_like(-value_) - to_unsigned_like(-bound_)
478  : to_unsigned_like(bound_) + to_unsigned_like(-value_)
479  )
480  : to_unsigned_like(bound_) - to_unsigned_like(value_);
481  }
482  constexpr auto size_impl(std::false_type) const {
483  return static_cast<std::size_t>(bound_ - value_);
484  }
485 
486  static constexpr W get_value(const iterator& i) {
487  return i.value_;
488  }
489  static constexpr Bound get_value(const sentinel& s) {
490  return s.bound_;
491  }
492  static constexpr unreachable_sentinel_t get_value(const unreachable_sentinel_t&) {
493  return unreachable_sentinel_t{};
494  }
495 
496  W value_ = W();
497  Bound bound_ = Bound();
498 };
499 
500 
501 // TODO: Implement constraints
502 template<typename W, typename Bound>
503 struct enable_borrowed_range<iota_view<W, Bound>> : std::true_type {};
504 
506 
507 namespace views {
508 namespace detail {
509 
511  template<typename W>
513  return ranges::iota_view<std::remove_reference_t<W>>(std::forward<W>(value));
514  }
515 
516  template<typename W, typename Bound, std::enable_if_t<conjunction<
517  disjunction<
521  >
522  >::value, int> = 0>
523  constexpr ranges::iota_view<std::remove_reference_t<W>, std::remove_reference_t<Bound>>
524  operator()(W&& value, Bound&& bound) const {
525  return ranges::iota_view<std::remove_reference_t<W>, std::remove_reference_t<Bound>>(std::forward<W>(value), std::forward<Bound>(bound));
526  }
527 };
528 
529 } // namespace detail
530 
533 
534 
540 
542 
543 } // namespace views
544 
545 } // namespace ranges
546 } // namespace vccc
547 
548 #endif // VCCC_RANGES_VIEWS_IOTA_HPP_
Definition: iota_view.hpp:207
constexpr iterator & operator--()
Definition: iota_view.hpp:248
constexpr W operator*() const noexcept(std::is_nothrow_copy_constructible< W >::value)
Definition: iota_view.hpp:220
constexpr friend std::enable_if_t< totally_ordered< W >::value, bool > operator>=(const iterator &x, const iterator &y)
Definition: iota_view.hpp:323
constexpr iterator(W value)
Definition: iota_view.hpp:218
constexpr friend std::enable_if_t< equality_comparable< W >::value, bool > operator==(const iterator &x, const iterator &y)
Definition: iota_view.hpp:303
constexpr void operator++(int)
Definition: iota_view.hpp:232
constexpr friend std::enable_if_t< totally_ordered< W >::value, bool > operator<(const iterator &x, const iterator &y)
Definition: iota_view.hpp:311
W value_type
Definition: iota_view.hpp:209
constexpr W operator[](difference_type n) const
Definition: iota_view.hpp:298
constexpr friend std::enable_if_t< totally_ordered< W >::value, bool > operator>(const iterator &x, const iterator &y)
Definition: iota_view.hpp:315
constexpr friend std::enable_if_t< detail::iv_advanceable< W >::value, iterator > operator+(iterator i, difference_type n)
Definition: iota_view.hpp:328
constexpr iterator & operator-=(difference_type n)
Definition: iota_view.hpp:282
constexpr friend std::enable_if_t< detail::iv_advanceable< W >::value, iterator > operator-(iterator i, difference_type n)
Definition: iota_view.hpp:339
constexpr iterator & operator+=(difference_type n)
Definition: iota_view.hpp:265
constexpr iterator operator--(int)
Definition: iota_view.hpp:255
constexpr iterator()
Definition: iota_view.hpp:216
constexpr friend std::enable_if_t< totally_ordered< W >::value, bool > operator<=(const iterator &x, const iterator &y)
Definition: iota_view.hpp:319
constexpr friend std::enable_if_t< detail::iv_advanceable< W >::value, iterator > operator+(difference_type n, iterator i)
Definition: iota_view.hpp:333
constexpr iterator operator++(int)
Definition: iota_view.hpp:238
constexpr friend std::enable_if_t< equality_comparable< W >::value, bool > operator!=(const iterator &x, const iterator &y)
Definition: iota_view.hpp:307
detail::iota_diff_t< W > difference_type
Definition: iota_view.hpp:210
typename detail::iota_view_iterator_concept< W >::type iterator_concept
Definition: iota_view.hpp:211
constexpr iterator & operator++()
Definition: iota_view.hpp:224
constexpr friend difference_type operator-(iterator x, iterator y)
Definition: iota_view.hpp:349
Definition: iota_view.hpp:379
constexpr sentinel()
Definition: iota_view.hpp:381
constexpr friend bool operator!=(const iterator &x, const sentinel &y)
Definition: iota_view.hpp:389
constexpr friend bool operator==(const iterator &x, const sentinel &y)
Definition: iota_view.hpp:385
constexpr friend iter_difference_t< W > operator-(const iterator &x, const sentinel &y)
Definition: iota_view.hpp:402
constexpr friend bool operator==(const sentinel &y, const iterator &x)
Definition: iota_view.hpp:392
constexpr friend iter_difference_t< W > operator-(const sentinel &x, const iterator &y)
Definition: iota_view.hpp:409
constexpr sentinel(Bound bound)
Definition: iota_view.hpp:383
constexpr friend bool operator!=(const sentinel &y, const iterator &x)
Definition: iota_view.hpp:395
Definition: iota_view.hpp:197
constexpr iota_view(type_identity_t< W > value, type_identity_t< Bound > bound)
Definition: iota_view.hpp:427
constexpr iota_view(iterator first, typename detail::iv_ctor_iterator_last< W, Bound, iota_view >::type last)
Definition: iota_view.hpp:430
constexpr auto size() const
Definition: iota_view.hpp:463
constexpr iota_view()
Definition: iota_view.hpp:423
constexpr iterator end() const
Definition: iota_view.hpp:447
constexpr iota_view(W value)
Definition: iota_view.hpp:425
constexpr iterator begin() const
Definition: iota_view.hpp:433
constexpr sentinel end() const
Definition: iota_view.hpp:441
constexpr bool empty() const
Definition: iota_view.hpp:451
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
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
constexpr VCCC_INLINE_OR_STATIC detail::iota_niebloid iota
Definition: iota_view.hpp:539
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
typename type_identity< T >::type type_identity_t
Definition: type_identity.hpp:22
void void_t
Definition: void_t.hpp:19
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
specifies that an object of a type can be copied, moved, and swapped
Definition: copyable.hpp:59
Definition: disjunction.hpp:22
Check if type models integer-like type (C++ 20 requirement)
Definition: is_integer_like.hpp:34
Definition: is_integer_like.hpp:48
Definition: negation.hpp:23
Definition: enable_borrowed_range.hpp:17
Definition: iota_view.hpp:510
constexpr iota_view< std::remove_reference_t< W > > operator()(W &&value) const
Definition: iota_view.hpp:512
constexpr ranges::iota_view< std::remove_reference_t< W >, std::remove_reference_t< Bound > > operator()(W &&value, Bound &&bound) const
Definition: iota_view.hpp:524
specifies that an object of a type can be copied, moved, swapped, and default constructed
Definition: semiregular.hpp:31
specifies that two different objects can be compared for equality with each other (in either order) u...
Definition: weakly_equality_comparable_with.hpp:51
Definition: weakly_incrementable.hpp:52