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 10 #ifndef _LIBCPP___RANGES_REPEAT_VIEW_H 11 #define _LIBCPP___RANGES_REPEAT_VIEW_H 12 13 #include <__assert> 14 #include <__concepts/constructible.h> 15 #include <__concepts/same_as.h> 16 #include <__concepts/semiregular.h> 17 #include <__config> 18 #include <__iterator/concepts.h> 19 #include <__iterator/iterator_traits.h> 20 #include <__iterator/unreachable_sentinel.h> 21 #include <__memory/addressof.h> 22 #include <__ranges/iota_view.h> 23 #include <__ranges/movable_box.h> 24 #include <__ranges/view_interface.h> 25 #include <__type_traits/decay.h> 26 #include <__type_traits/is_object.h> 27 #include <__type_traits/make_unsigned.h> 28 #include <__type_traits/remove_cv.h> 29 #include <__utility/forward.h> 30 #include <__utility/in_place.h> 31 #include <__utility/move.h> 32 #include <__utility/piecewise_construct.h> 33 #include <tuple> 34 35 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 36 # pragma GCC system_header 37 #endif 38 39 _LIBCPP_PUSH_MACROS 40 #include <__undef_macros> 41 42 _LIBCPP_BEGIN_NAMESPACE_STD 43 44 #if _LIBCPP_STD_VER >= 23 45 46 namespace ranges { 47 48 template <class _Tp> 49 concept __integer_like_with_usable_difference_type = 50 __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>); 51 52 template <class _Tp> 53 struct __repeat_view_iterator_difference { 54 using type = _IotaDiffT<_Tp>; 55 }; 56 57 template <__signed_integer_like _Tp> 58 struct __repeat_view_iterator_difference<_Tp> { 59 using type = _Tp; 60 }; 61 62 template <class _Tp> 63 using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type; 64 65 namespace views::__drop { 66 struct __fn; 67 } // namespace views::__drop 68 69 namespace views::__take { 70 struct __fn; 71 } // namespace views::__take 72 73 template <move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t> 74 requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 75 (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 76 class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS repeat_view : public view_interface<repeat_view<_Tp, _Bound>> { 77 friend struct views::__take::__fn; 78 friend struct views::__drop::__fn; 79 class __iterator; 80 81 public: 82 _LIBCPP_HIDE_FROM_ABI repeat_view() 83 requires default_initializable<_Tp> 84 = default; 85 86 _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound()) 87 requires copy_constructible<_Tp> 88 : __value_(in_place, __value), __bound_(__bound_sentinel) { 89 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 90 _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 91 } 92 93 _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) 94 : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { 95 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 96 _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 97 } 98 99 template <class... _TpArgs, class... _BoundArgs> 100 requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>) 101 _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( 102 piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) 103 : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), 104 __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) { 105 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 106 _LIBCPP_ASSERT_UNCATEGORIZED( 107 __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative"); 108 } 109 110 _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } 111 112 _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const 113 requires(!same_as<_Bound, unreachable_sentinel_t>) 114 { 115 return __iterator(std::addressof(*__value_), __bound_); 116 } 117 118 _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } 119 120 _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 121 requires(!same_as<_Bound, unreachable_sentinel_t>) 122 { 123 return std::__to_unsigned_like(__bound_); 124 } 125 126 private: 127 _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Tp> __value_; 128 _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); 129 }; 130 131 template <class _Tp, class _Bound = unreachable_sentinel_t> 132 repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>; 133 134 // [range.repeat.iterator] 135 template <move_constructible _Tp, semiregular _Bound> 136 requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 137 (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 138 class repeat_view<_Tp, _Bound>::__iterator { 139 friend class repeat_view; 140 141 using _IndexT = conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; 142 143 _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) 144 : __value_(__value), __current_(__bound_sentinel) {} 145 146 public: 147 using iterator_concept = random_access_iterator_tag; 148 using iterator_category = random_access_iterator_tag; 149 using value_type = _Tp; 150 using difference_type = __repeat_view_iterator_difference_t<_IndexT>; 151 152 _LIBCPP_HIDE_FROM_ABI __iterator() = default; 153 154 _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } 155 156 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 157 ++__current_; 158 return *this; 159 } 160 161 _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { 162 auto __tmp = *this; 163 ++*this; 164 return __tmp; 165 } 166 167 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { 168 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 169 _LIBCPP_ASSERT_UNCATEGORIZED(__current_ > 0, "The value of bound must be greater than or equal to 0"); 170 --__current_; 171 return *this; 172 } 173 174 _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { 175 auto __tmp = *this; 176 --*this; 177 return __tmp; 178 } 179 180 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { 181 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 182 _LIBCPP_ASSERT_UNCATEGORIZED(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0"); 183 __current_ += __n; 184 return *this; 185 } 186 187 _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { 188 if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 189 _LIBCPP_ASSERT_UNCATEGORIZED(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0"); 190 __current_ -= __n; 191 return *this; 192 } 193 194 _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } 195 196 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { 197 return __x.__current_ == __y.__current_; 198 } 199 200 _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { 201 return __x.__current_ <=> __y.__current_; 202 } 203 204 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { 205 __i += __n; 206 return __i; 207 } 208 209 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { 210 __i += __n; 211 return __i; 212 } 213 214 _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { 215 __i -= __n; 216 return __i; 217 } 218 219 _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { 220 return static_cast<difference_type>(__x.__current_) - static_cast<difference_type>(__y.__current_); 221 } 222 223 private: 224 const _Tp* __value_ = nullptr; 225 _IndexT __current_ = _IndexT(); 226 }; 227 228 // clang-format off 229 namespace views { 230 namespace __repeat { 231 struct __fn { 232 template <class _Tp> 233 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) 234 noexcept(noexcept(ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)))) 235 -> decltype( ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value))) 236 { return ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)); } 237 238 template <class _Tp, class _Bound> 239 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) 240 noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) 241 -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) 242 { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } 243 }; 244 } // namespace __repeat 245 // clang-format on 246 247 inline namespace __cpo { 248 inline constexpr auto repeat = __repeat::__fn{}; 249 } // namespace __cpo 250 } // namespace views 251 252 template <class _Tp> 253 inline constexpr bool __is_repeat_specialization = false; 254 255 template <class _Tp, class _Bound> 256 inline constexpr bool __is_repeat_specialization<repeat_view<_Tp, _Bound>> = true; 257 258 } // namespace ranges 259 260 #endif // _LIBCPP_STD_VER >= 23 261 262 _LIBCPP_END_NAMESPACE_STD 263 264 _LIBCPP_POP_MACROS 265 266 #endif // _LIBCPP___RANGES_REPEAT_VIEW_H 267