106c3fb27SDimitry Andric // -*- C++ -*- 206c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 306c3fb27SDimitry Andric // 406c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 506c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 606c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 706c3fb27SDimitry Andric // 806c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 906c3fb27SDimitry Andric 1006c3fb27SDimitry Andric #ifndef _LIBCPP___RANGES_REPEAT_VIEW_H 1106c3fb27SDimitry Andric #define _LIBCPP___RANGES_REPEAT_VIEW_H 1206c3fb27SDimitry Andric 13*0fca6ea1SDimitry Andric #include <__assert> 1406c3fb27SDimitry Andric #include <__concepts/constructible.h> 1506c3fb27SDimitry Andric #include <__concepts/same_as.h> 1606c3fb27SDimitry Andric #include <__concepts/semiregular.h> 1706c3fb27SDimitry Andric #include <__config> 1806c3fb27SDimitry Andric #include <__iterator/concepts.h> 1906c3fb27SDimitry Andric #include <__iterator/iterator_traits.h> 2006c3fb27SDimitry Andric #include <__iterator/unreachable_sentinel.h> 2106c3fb27SDimitry Andric #include <__memory/addressof.h> 2206c3fb27SDimitry Andric #include <__ranges/iota_view.h> 2306c3fb27SDimitry Andric #include <__ranges/movable_box.h> 2406c3fb27SDimitry Andric #include <__ranges/view_interface.h> 25*0fca6ea1SDimitry Andric #include <__type_traits/decay.h> 2606c3fb27SDimitry Andric #include <__type_traits/is_object.h> 2706c3fb27SDimitry Andric #include <__type_traits/make_unsigned.h> 2806c3fb27SDimitry Andric #include <__type_traits/remove_cv.h> 2906c3fb27SDimitry Andric #include <__utility/forward.h> 3006c3fb27SDimitry Andric #include <__utility/in_place.h> 3106c3fb27SDimitry Andric #include <__utility/move.h> 3206c3fb27SDimitry Andric #include <__utility/piecewise_construct.h> 3306c3fb27SDimitry Andric #include <tuple> 3406c3fb27SDimitry Andric 3506c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 3606c3fb27SDimitry Andric # pragma GCC system_header 3706c3fb27SDimitry Andric #endif 3806c3fb27SDimitry Andric 39b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 40b3edf446SDimitry Andric #include <__undef_macros> 41b3edf446SDimitry Andric 4206c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 4306c3fb27SDimitry Andric 4406c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23 4506c3fb27SDimitry Andric 4606c3fb27SDimitry Andric namespace ranges { 4706c3fb27SDimitry Andric 4806c3fb27SDimitry Andric template <class _Tp> 4906c3fb27SDimitry Andric concept __integer_like_with_usable_difference_type = 5006c3fb27SDimitry Andric __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>); 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric template <class _Tp> 5306c3fb27SDimitry Andric struct __repeat_view_iterator_difference { 5406c3fb27SDimitry Andric using type = _IotaDiffT<_Tp>; 5506c3fb27SDimitry Andric }; 5606c3fb27SDimitry Andric 5706c3fb27SDimitry Andric template <__signed_integer_like _Tp> 5806c3fb27SDimitry Andric struct __repeat_view_iterator_difference<_Tp> { 5906c3fb27SDimitry Andric using type = _Tp; 6006c3fb27SDimitry Andric }; 6106c3fb27SDimitry Andric 6206c3fb27SDimitry Andric template <class _Tp> 6306c3fb27SDimitry Andric using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type; 6406c3fb27SDimitry Andric 6506c3fb27SDimitry Andric namespace views::__drop { 6606c3fb27SDimitry Andric struct __fn; 6706c3fb27SDimitry Andric } // namespace views::__drop 6806c3fb27SDimitry Andric 6906c3fb27SDimitry Andric namespace views::__take { 7006c3fb27SDimitry Andric struct __fn; 7106c3fb27SDimitry Andric } // namespace views::__take 7206c3fb27SDimitry Andric 7306c3fb27SDimitry Andric template <move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t> 7406c3fb27SDimitry Andric requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 7506c3fb27SDimitry Andric (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 767a6dacacSDimitry Andric class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS repeat_view : public view_interface<repeat_view<_Tp, _Bound>> { 7706c3fb27SDimitry Andric friend struct views::__take::__fn; 7806c3fb27SDimitry Andric friend struct views::__drop::__fn; 7906c3fb27SDimitry Andric class __iterator; 8006c3fb27SDimitry Andric 8106c3fb27SDimitry Andric public: 8206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI repeat_view() 8306c3fb27SDimitry Andric requires default_initializable<_Tp> 8406c3fb27SDimitry Andric = default; 8506c3fb27SDimitry Andric 8606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound()) 8706c3fb27SDimitry Andric requires copy_constructible<_Tp> 8806c3fb27SDimitry Andric : __value_(in_place, __value), __bound_(__bound_sentinel) { 8906c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 905f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 9106c3fb27SDimitry Andric } 9206c3fb27SDimitry Andric 9306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) 9406c3fb27SDimitry Andric : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { 9506c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 965f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 9706c3fb27SDimitry Andric } 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric template <class... _TpArgs, class... _BoundArgs> 10006c3fb27SDimitry Andric requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>) 10106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( 10206c3fb27SDimitry Andric piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) 10306c3fb27SDimitry Andric : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), 10406c3fb27SDimitry Andric __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) { 10506c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 1065f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED( 10706c3fb27SDimitry Andric __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative"); 10806c3fb27SDimitry Andric } 10906c3fb27SDimitry Andric 11006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } 11106c3fb27SDimitry Andric 11206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const 11306c3fb27SDimitry Andric requires(!same_as<_Bound, unreachable_sentinel_t>) 11406c3fb27SDimitry Andric { 11506c3fb27SDimitry Andric return __iterator(std::addressof(*__value_), __bound_); 11606c3fb27SDimitry Andric } 11706c3fb27SDimitry Andric 11806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } 11906c3fb27SDimitry Andric 12006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 12106c3fb27SDimitry Andric requires(!same_as<_Bound, unreachable_sentinel_t>) 12206c3fb27SDimitry Andric { 12306c3fb27SDimitry Andric return std::__to_unsigned_like(__bound_); 12406c3fb27SDimitry Andric } 12506c3fb27SDimitry Andric 12606c3fb27SDimitry Andric private: 127647cbc5dSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Tp> __value_; 12806c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); 12906c3fb27SDimitry Andric }; 13006c3fb27SDimitry Andric 131*0fca6ea1SDimitry Andric template <class _Tp, class _Bound = unreachable_sentinel_t> 132*0fca6ea1SDimitry Andric repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>; 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric // [range.repeat.iterator] 13506c3fb27SDimitry Andric template <move_constructible _Tp, semiregular _Bound> 13606c3fb27SDimitry Andric requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 13706c3fb27SDimitry Andric (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 13806c3fb27SDimitry Andric class repeat_view<_Tp, _Bound>::__iterator { 13906c3fb27SDimitry Andric friend class repeat_view; 14006c3fb27SDimitry Andric 14106c3fb27SDimitry Andric using _IndexT = conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) 14406c3fb27SDimitry Andric : __value_(__value), __current_(__bound_sentinel) {} 14506c3fb27SDimitry Andric 14606c3fb27SDimitry Andric public: 14706c3fb27SDimitry Andric using iterator_concept = random_access_iterator_tag; 14806c3fb27SDimitry Andric using iterator_category = random_access_iterator_tag; 14906c3fb27SDimitry Andric using value_type = _Tp; 15006c3fb27SDimitry Andric using difference_type = __repeat_view_iterator_difference_t<_IndexT>; 15106c3fb27SDimitry Andric 15206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 15306c3fb27SDimitry Andric 15406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } 15506c3fb27SDimitry Andric 15606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 15706c3fb27SDimitry Andric ++__current_; 15806c3fb27SDimitry Andric return *this; 15906c3fb27SDimitry Andric } 16006c3fb27SDimitry Andric 16106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { 16206c3fb27SDimitry Andric auto __tmp = *this; 16306c3fb27SDimitry Andric ++*this; 16406c3fb27SDimitry Andric return __tmp; 16506c3fb27SDimitry Andric } 16606c3fb27SDimitry Andric 16706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { 16806c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 1695f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ > 0, "The value of bound must be greater than or equal to 0"); 17006c3fb27SDimitry Andric --__current_; 17106c3fb27SDimitry Andric return *this; 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { 17506c3fb27SDimitry Andric auto __tmp = *this; 17606c3fb27SDimitry Andric --*this; 17706c3fb27SDimitry Andric return __tmp; 17806c3fb27SDimitry Andric } 17906c3fb27SDimitry Andric 18006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { 18106c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 1825f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0"); 18306c3fb27SDimitry Andric __current_ += __n; 18406c3fb27SDimitry Andric return *this; 18506c3fb27SDimitry Andric } 18606c3fb27SDimitry Andric 18706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { 18806c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 1895f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0"); 19006c3fb27SDimitry Andric __current_ -= __n; 19106c3fb27SDimitry Andric return *this; 19206c3fb27SDimitry Andric } 19306c3fb27SDimitry Andric 19406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } 19506c3fb27SDimitry Andric 19606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { 19706c3fb27SDimitry Andric return __x.__current_ == __y.__current_; 19806c3fb27SDimitry Andric } 19906c3fb27SDimitry Andric 20006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { 20106c3fb27SDimitry Andric return __x.__current_ <=> __y.__current_; 20206c3fb27SDimitry Andric } 20306c3fb27SDimitry Andric 20406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { 20506c3fb27SDimitry Andric __i += __n; 20606c3fb27SDimitry Andric return __i; 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { 21006c3fb27SDimitry Andric __i += __n; 21106c3fb27SDimitry Andric return __i; 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { 21506c3fb27SDimitry Andric __i -= __n; 21606c3fb27SDimitry Andric return __i; 21706c3fb27SDimitry Andric } 21806c3fb27SDimitry Andric 21906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { 22006c3fb27SDimitry Andric return static_cast<difference_type>(__x.__current_) - static_cast<difference_type>(__y.__current_); 22106c3fb27SDimitry Andric } 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric private: 22406c3fb27SDimitry Andric const _Tp* __value_ = nullptr; 22506c3fb27SDimitry Andric _IndexT __current_ = _IndexT(); 22606c3fb27SDimitry Andric }; 22706c3fb27SDimitry Andric 22806c3fb27SDimitry Andric // clang-format off 22906c3fb27SDimitry Andric namespace views { 23006c3fb27SDimitry Andric namespace __repeat { 23106c3fb27SDimitry Andric struct __fn { 23206c3fb27SDimitry Andric template <class _Tp> 233*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) 234*0fca6ea1SDimitry Andric noexcept(noexcept(ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)))) 235*0fca6ea1SDimitry Andric -> decltype( ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value))) 236*0fca6ea1SDimitry Andric { return ranges::repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value)); } 23706c3fb27SDimitry Andric 23806c3fb27SDimitry Andric template <class _Tp, class _Bound> 239*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) 24006c3fb27SDimitry Andric noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) 24106c3fb27SDimitry Andric -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) 24206c3fb27SDimitry Andric { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } 24306c3fb27SDimitry Andric }; 24406c3fb27SDimitry Andric } // namespace __repeat 24506c3fb27SDimitry Andric // clang-format on 24606c3fb27SDimitry Andric 24706c3fb27SDimitry Andric inline namespace __cpo { 24806c3fb27SDimitry Andric inline constexpr auto repeat = __repeat::__fn{}; 24906c3fb27SDimitry Andric } // namespace __cpo 25006c3fb27SDimitry Andric } // namespace views 25106c3fb27SDimitry Andric 25206c3fb27SDimitry Andric template <class _Tp> 25306c3fb27SDimitry Andric inline constexpr bool __is_repeat_specialization = false; 25406c3fb27SDimitry Andric 25506c3fb27SDimitry Andric template <class _Tp, class _Bound> 25606c3fb27SDimitry Andric inline constexpr bool __is_repeat_specialization<repeat_view<_Tp, _Bound>> = true; 25706c3fb27SDimitry Andric 25806c3fb27SDimitry Andric } // namespace ranges 25906c3fb27SDimitry Andric 26006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 23 26106c3fb27SDimitry Andric 26206c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 26306c3fb27SDimitry Andric 264b3edf446SDimitry Andric _LIBCPP_POP_MACROS 265b3edf446SDimitry Andric 26606c3fb27SDimitry Andric #endif // _LIBCPP___RANGES_REPEAT_VIEW_H 267