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 1306c3fb27SDimitry Andric #include <__concepts/constructible.h> 1406c3fb27SDimitry Andric #include <__concepts/same_as.h> 1506c3fb27SDimitry Andric #include <__concepts/semiregular.h> 1606c3fb27SDimitry Andric #include <__config> 1706c3fb27SDimitry Andric #include <__iterator/concepts.h> 1806c3fb27SDimitry Andric #include <__iterator/iterator_traits.h> 1906c3fb27SDimitry Andric #include <__iterator/unreachable_sentinel.h> 2006c3fb27SDimitry Andric #include <__memory/addressof.h> 2106c3fb27SDimitry Andric #include <__ranges/iota_view.h> 2206c3fb27SDimitry Andric #include <__ranges/movable_box.h> 2306c3fb27SDimitry Andric #include <__ranges/view_interface.h> 2406c3fb27SDimitry Andric #include <__type_traits/is_object.h> 2506c3fb27SDimitry Andric #include <__type_traits/make_unsigned.h> 2606c3fb27SDimitry Andric #include <__type_traits/remove_cv.h> 2706c3fb27SDimitry Andric #include <__utility/forward.h> 2806c3fb27SDimitry Andric #include <__utility/in_place.h> 2906c3fb27SDimitry Andric #include <__utility/move.h> 3006c3fb27SDimitry Andric #include <__utility/piecewise_construct.h> 3106c3fb27SDimitry Andric #include <tuple> 3206c3fb27SDimitry Andric 3306c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 3406c3fb27SDimitry Andric # pragma GCC system_header 3506c3fb27SDimitry Andric #endif 3606c3fb27SDimitry Andric 3706c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23 4006c3fb27SDimitry Andric 4106c3fb27SDimitry Andric namespace ranges { 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric template <class _Tp> 4406c3fb27SDimitry Andric concept __integer_like_with_usable_difference_type = 4506c3fb27SDimitry Andric __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>); 4606c3fb27SDimitry Andric 4706c3fb27SDimitry Andric template <class _Tp> 4806c3fb27SDimitry Andric struct __repeat_view_iterator_difference { 4906c3fb27SDimitry Andric using type = _IotaDiffT<_Tp>; 5006c3fb27SDimitry Andric }; 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric template <__signed_integer_like _Tp> 5306c3fb27SDimitry Andric struct __repeat_view_iterator_difference<_Tp> { 5406c3fb27SDimitry Andric using type = _Tp; 5506c3fb27SDimitry Andric }; 5606c3fb27SDimitry Andric 5706c3fb27SDimitry Andric template <class _Tp> 5806c3fb27SDimitry Andric using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type; 5906c3fb27SDimitry Andric 6006c3fb27SDimitry Andric namespace views::__drop { 6106c3fb27SDimitry Andric struct __fn; 6206c3fb27SDimitry Andric } // namespace views::__drop 6306c3fb27SDimitry Andric 6406c3fb27SDimitry Andric namespace views::__take { 6506c3fb27SDimitry Andric struct __fn; 6606c3fb27SDimitry Andric } // namespace views::__take 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric template <move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t> 6906c3fb27SDimitry Andric requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 7006c3fb27SDimitry Andric (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 7106c3fb27SDimitry Andric class repeat_view : public view_interface<repeat_view<_Tp, _Bound>> { 7206c3fb27SDimitry Andric friend struct views::__take::__fn; 7306c3fb27SDimitry Andric friend struct views::__drop::__fn; 7406c3fb27SDimitry Andric class __iterator; 7506c3fb27SDimitry Andric 7606c3fb27SDimitry Andric public: 7706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI repeat_view() 7806c3fb27SDimitry Andric requires default_initializable<_Tp> 7906c3fb27SDimitry Andric = default; 8006c3fb27SDimitry Andric 8106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound()) 8206c3fb27SDimitry Andric requires copy_constructible<_Tp> 8306c3fb27SDimitry Andric : __value_(in_place, __value), __bound_(__bound_sentinel) { 8406c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 85*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 8606c3fb27SDimitry Andric } 8706c3fb27SDimitry Andric 8806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) 8906c3fb27SDimitry Andric : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { 9006c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 91*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); 9206c3fb27SDimitry Andric } 9306c3fb27SDimitry Andric 9406c3fb27SDimitry Andric template <class... _TpArgs, class... _BoundArgs> 9506c3fb27SDimitry Andric requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>) 9606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( 9706c3fb27SDimitry Andric piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) 9806c3fb27SDimitry Andric : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), 9906c3fb27SDimitry Andric __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) { 10006c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 101*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED( 10206c3fb27SDimitry Andric __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative"); 10306c3fb27SDimitry Andric } 10406c3fb27SDimitry Andric 10506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } 10606c3fb27SDimitry Andric 10706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const 10806c3fb27SDimitry Andric requires(!same_as<_Bound, unreachable_sentinel_t>) 10906c3fb27SDimitry Andric { 11006c3fb27SDimitry Andric return __iterator(std::addressof(*__value_), __bound_); 11106c3fb27SDimitry Andric } 11206c3fb27SDimitry Andric 11306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 11606c3fb27SDimitry Andric requires(!same_as<_Bound, unreachable_sentinel_t>) 11706c3fb27SDimitry Andric { 11806c3fb27SDimitry Andric return std::__to_unsigned_like(__bound_); 11906c3fb27SDimitry Andric } 12006c3fb27SDimitry Andric 12106c3fb27SDimitry Andric private: 12206c3fb27SDimitry Andric __movable_box<_Tp> __value_; 12306c3fb27SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); 12406c3fb27SDimitry Andric }; 12506c3fb27SDimitry Andric 12606c3fb27SDimitry Andric template <class _Tp, class _Bound> 12706c3fb27SDimitry Andric repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; 12806c3fb27SDimitry Andric 12906c3fb27SDimitry Andric // [range.repeat.iterator] 13006c3fb27SDimitry Andric template <move_constructible _Tp, semiregular _Bound> 13106c3fb27SDimitry Andric requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && 13206c3fb27SDimitry Andric (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) 13306c3fb27SDimitry Andric class repeat_view<_Tp, _Bound>::__iterator { 13406c3fb27SDimitry Andric friend class repeat_view; 13506c3fb27SDimitry Andric 13606c3fb27SDimitry Andric using _IndexT = conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; 13706c3fb27SDimitry Andric 13806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) 13906c3fb27SDimitry Andric : __value_(__value), __current_(__bound_sentinel) {} 14006c3fb27SDimitry Andric 14106c3fb27SDimitry Andric public: 14206c3fb27SDimitry Andric using iterator_concept = random_access_iterator_tag; 14306c3fb27SDimitry Andric using iterator_category = random_access_iterator_tag; 14406c3fb27SDimitry Andric using value_type = _Tp; 14506c3fb27SDimitry Andric using difference_type = __repeat_view_iterator_difference_t<_IndexT>; 14606c3fb27SDimitry Andric 14706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 14806c3fb27SDimitry Andric 14906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } 15006c3fb27SDimitry Andric 15106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 15206c3fb27SDimitry Andric ++__current_; 15306c3fb27SDimitry Andric return *this; 15406c3fb27SDimitry Andric } 15506c3fb27SDimitry Andric 15606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { 15706c3fb27SDimitry Andric auto __tmp = *this; 15806c3fb27SDimitry Andric ++*this; 15906c3fb27SDimitry Andric return __tmp; 16006c3fb27SDimitry Andric } 16106c3fb27SDimitry Andric 16206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { 16306c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 164*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ > 0, "The value of bound must be greater than or equal to 0"); 16506c3fb27SDimitry Andric --__current_; 16606c3fb27SDimitry Andric return *this; 16706c3fb27SDimitry Andric } 16806c3fb27SDimitry Andric 16906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { 17006c3fb27SDimitry Andric auto __tmp = *this; 17106c3fb27SDimitry Andric --*this; 17206c3fb27SDimitry Andric return __tmp; 17306c3fb27SDimitry Andric } 17406c3fb27SDimitry Andric 17506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { 17606c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 177*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0"); 17806c3fb27SDimitry Andric __current_ += __n; 17906c3fb27SDimitry Andric return *this; 18006c3fb27SDimitry Andric } 18106c3fb27SDimitry Andric 18206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { 18306c3fb27SDimitry Andric if constexpr (!same_as<_Bound, unreachable_sentinel_t>) 184*5f757f3fSDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0"); 18506c3fb27SDimitry Andric __current_ -= __n; 18606c3fb27SDimitry Andric return *this; 18706c3fb27SDimitry Andric } 18806c3fb27SDimitry Andric 18906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } 19006c3fb27SDimitry Andric 19106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { 19206c3fb27SDimitry Andric return __x.__current_ == __y.__current_; 19306c3fb27SDimitry Andric } 19406c3fb27SDimitry Andric 19506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { 19606c3fb27SDimitry Andric return __x.__current_ <=> __y.__current_; 19706c3fb27SDimitry Andric } 19806c3fb27SDimitry Andric 19906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { 20006c3fb27SDimitry Andric __i += __n; 20106c3fb27SDimitry Andric return __i; 20206c3fb27SDimitry Andric } 20306c3fb27SDimitry Andric 20406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { 20506c3fb27SDimitry Andric __i += __n; 20606c3fb27SDimitry Andric return __i; 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { 21006c3fb27SDimitry Andric __i -= __n; 21106c3fb27SDimitry Andric return __i; 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { 21506c3fb27SDimitry Andric return static_cast<difference_type>(__x.__current_) - static_cast<difference_type>(__y.__current_); 21606c3fb27SDimitry Andric } 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric private: 21906c3fb27SDimitry Andric const _Tp* __value_ = nullptr; 22006c3fb27SDimitry Andric _IndexT __current_ = _IndexT(); 22106c3fb27SDimitry Andric }; 22206c3fb27SDimitry Andric 22306c3fb27SDimitry Andric // clang-format off 22406c3fb27SDimitry Andric namespace views { 22506c3fb27SDimitry Andric namespace __repeat { 22606c3fb27SDimitry Andric struct __fn { 22706c3fb27SDimitry Andric template <class _Tp> 22806c3fb27SDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const 22906c3fb27SDimitry Andric noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) 23006c3fb27SDimitry Andric -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) 23106c3fb27SDimitry Andric { return ranges::repeat_view(std::forward<_Tp>(__value)); } 23206c3fb27SDimitry Andric 23306c3fb27SDimitry Andric 23406c3fb27SDimitry Andric template <class _Tp, class _Bound> 23506c3fb27SDimitry Andric _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const 23606c3fb27SDimitry Andric noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) 23706c3fb27SDimitry Andric -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) 23806c3fb27SDimitry Andric { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } 23906c3fb27SDimitry Andric }; 24006c3fb27SDimitry Andric } // namespace __repeat 24106c3fb27SDimitry Andric // clang-format on 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric inline namespace __cpo { 24406c3fb27SDimitry Andric inline constexpr auto repeat = __repeat::__fn{}; 24506c3fb27SDimitry Andric } // namespace __cpo 24606c3fb27SDimitry Andric } // namespace views 24706c3fb27SDimitry Andric 24806c3fb27SDimitry Andric template <class _Tp> 24906c3fb27SDimitry Andric inline constexpr bool __is_repeat_specialization = false; 25006c3fb27SDimitry Andric 25106c3fb27SDimitry Andric template <class _Tp, class _Bound> 25206c3fb27SDimitry Andric inline constexpr bool __is_repeat_specialization<repeat_view<_Tp, _Bound>> = true; 25306c3fb27SDimitry Andric 25406c3fb27SDimitry Andric } // namespace ranges 25506c3fb27SDimitry Andric 25606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 23 25706c3fb27SDimitry Andric 25806c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD 25906c3fb27SDimitry Andric 26006c3fb27SDimitry Andric #endif // _LIBCPP___RANGES_REPEAT_VIEW_H 261