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