repeat_view.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___RANGES_REPEAT_VIEW_H
  10. #define _LIBCPP___RANGES_REPEAT_VIEW_H
  11. #include <__assert>
  12. #include <__concepts/constructible.h>
  13. #include <__concepts/same_as.h>
  14. #include <__concepts/semiregular.h>
  15. #include <__config>
  16. #include <__iterator/concepts.h>
  17. #include <__iterator/iterator_traits.h>
  18. #include <__iterator/unreachable_sentinel.h>
  19. #include <__memory/addressof.h>
  20. #include <__ranges/iota_view.h>
  21. #include <__ranges/movable_box.h>
  22. #include <__ranges/view_interface.h>
  23. #include <__type_traits/is_object.h>
  24. #include <__type_traits/make_unsigned.h>
  25. #include <__type_traits/remove_cv.h>
  26. #include <__utility/forward.h>
  27. #include <__utility/in_place.h>
  28. #include <__utility/move.h>
  29. #include <__utility/piecewise_construct.h>
  30. #include <tuple>
  31. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  32. # pragma GCC system_header
  33. #endif
  34. _LIBCPP_PUSH_MACROS
  35. #include <__undef_macros>
  36. _LIBCPP_BEGIN_NAMESPACE_STD
  37. #if _LIBCPP_STD_VER >= 23
  38. namespace ranges {
  39. template <class _Tp>
  40. concept __integer_like_with_usable_difference_type =
  41. __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>);
  42. template <class _Tp>
  43. struct __repeat_view_iterator_difference {
  44. using type = _IotaDiffT<_Tp>;
  45. };
  46. template <__signed_integer_like _Tp>
  47. struct __repeat_view_iterator_difference<_Tp> {
  48. using type = _Tp;
  49. };
  50. template <class _Tp>
  51. using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type;
  52. namespace views::__drop {
  53. struct __fn;
  54. } // namespace views::__drop
  55. namespace views::__take {
  56. struct __fn;
  57. } // namespace views::__take
  58. template <move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t>
  59. requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> &&
  60. (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>))
  61. class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS repeat_view : public view_interface<repeat_view<_Tp, _Bound>> {
  62. friend struct views::__take::__fn;
  63. friend struct views::__drop::__fn;
  64. class __iterator;
  65. public:
  66. _LIBCPP_HIDE_FROM_ABI repeat_view()
  67. requires default_initializable<_Tp>
  68. = default;
  69. _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound())
  70. requires copy_constructible<_Tp>
  71. : __value_(in_place, __value), __bound_(__bound_sentinel) {
  72. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  73. _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0");
  74. }
  75. _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound())
  76. : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) {
  77. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  78. _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0");
  79. }
  80. template <class... _TpArgs, class... _BoundArgs>
  81. requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>)
  82. _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(
  83. piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{})
  84. : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))),
  85. __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) {
  86. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  87. _LIBCPP_ASSERT_UNCATEGORIZED(
  88. __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative");
  89. }
  90. _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); }
  91. _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const
  92. requires(!same_as<_Bound, unreachable_sentinel_t>)
  93. {
  94. return __iterator(std::addressof(*__value_), __bound_);
  95. }
  96. _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; }
  97. _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
  98. requires(!same_as<_Bound, unreachable_sentinel_t>)
  99. {
  100. return std::__to_unsigned_like(__bound_);
  101. }
  102. private:
  103. _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Tp> __value_;
  104. _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound();
  105. };
  106. template <class _Tp, class _Bound>
  107. repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>;
  108. // [range.repeat.iterator]
  109. template <move_constructible _Tp, semiregular _Bound>
  110. requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> &&
  111. (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>))
  112. class repeat_view<_Tp, _Bound>::__iterator {
  113. friend class repeat_view;
  114. using _IndexT = conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>;
  115. _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT())
  116. : __value_(__value), __current_(__bound_sentinel) {}
  117. public:
  118. using iterator_concept = random_access_iterator_tag;
  119. using iterator_category = random_access_iterator_tag;
  120. using value_type = _Tp;
  121. using difference_type = __repeat_view_iterator_difference_t<_IndexT>;
  122. _LIBCPP_HIDE_FROM_ABI __iterator() = default;
  123. _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; }
  124. _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
  125. ++__current_;
  126. return *this;
  127. }
  128. _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) {
  129. auto __tmp = *this;
  130. ++*this;
  131. return __tmp;
  132. }
  133. _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() {
  134. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  135. _LIBCPP_ASSERT_UNCATEGORIZED(__current_ > 0, "The value of bound must be greater than or equal to 0");
  136. --__current_;
  137. return *this;
  138. }
  139. _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) {
  140. auto __tmp = *this;
  141. --*this;
  142. return __tmp;
  143. }
  144. _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) {
  145. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  146. _LIBCPP_ASSERT_UNCATEGORIZED(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0");
  147. __current_ += __n;
  148. return *this;
  149. }
  150. _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) {
  151. if constexpr (!same_as<_Bound, unreachable_sentinel_t>)
  152. _LIBCPP_ASSERT_UNCATEGORIZED(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0");
  153. __current_ -= __n;
  154. return *this;
  155. }
  156. _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); }
  157. _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
  158. return __x.__current_ == __y.__current_;
  159. }
  160. _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) {
  161. return __x.__current_ <=> __y.__current_;
  162. }
  163. _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) {
  164. __i += __n;
  165. return __i;
  166. }
  167. _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) {
  168. __i += __n;
  169. return __i;
  170. }
  171. _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) {
  172. __i -= __n;
  173. return __i;
  174. }
  175. _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) {
  176. return static_cast<difference_type>(__x.__current_) - static_cast<difference_type>(__y.__current_);
  177. }
  178. private:
  179. const _Tp* __value_ = nullptr;
  180. _IndexT __current_ = _IndexT();
  181. };
  182. // clang-format off
  183. namespace views {
  184. namespace __repeat {
  185. struct __fn {
  186. template <class _Tp>
  187. _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const
  188. noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value))))
  189. -> decltype( ranges::repeat_view(std::forward<_Tp>(__value)))
  190. { return ranges::repeat_view(std::forward<_Tp>(__value)); }
  191. template <class _Tp, class _Bound>
  192. _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const
  193. noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))))
  194. -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))
  195. { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); }
  196. };
  197. } // namespace __repeat
  198. // clang-format on
  199. inline namespace __cpo {
  200. inline constexpr auto repeat = __repeat::__fn{};
  201. } // namespace __cpo
  202. } // namespace views
  203. template <class _Tp>
  204. inline constexpr bool __is_repeat_specialization = false;
  205. template <class _Tp, class _Bound>
  206. inline constexpr bool __is_repeat_specialization<repeat_view<_Tp, _Bound>> = true;
  207. } // namespace ranges
  208. #endif // _LIBCPP_STD_VER >= 23
  209. _LIBCPP_END_NAMESPACE_STD
  210. _LIBCPP_POP_MACROS
  211. #endif // _LIBCPP___RANGES_REPEAT_VIEW_H