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