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