diff --git a/libcxx/include/__ranges/repeat_view.h b/libcxx/include/__ranges/repeat_view.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/repeat_view.h @@ -0,0 +1,217 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_REPEAT_VIEW_H +#define _LIBCPP___RANGES_REPEAT_VIEW_H + +#include <__concepts/constructible.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__ranges/copyable_box.h> +#include <__ranges/iota_view.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/view_interface.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/piecewise_construct.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define _LIBCPP_STD_VER 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges { +template + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) +class repeat_view : public view_interface> { +private: + struct __iterator; + + __copyable_box<_Tp> __value_; + _Bound __bound_ = _Bound(); + +public: + _LIBCPP_HIDE_FROM_ABI repeat_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound = _Bound()) + : __value_(__value), __bound_(__bound) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must greater equal than 0"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound = _Bound()) + : __value_(std::move(__value)), __bound_(__bound) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must greater equal than 0"); + } + + template + requires constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( + piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) + : __value_(std::forward<_TpArgs>(__value_args)...), __bound_(std::forward<_BoundArgs>(__bound_args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const + requires(!same_as) + { + return __iterator(std::addressof(*__value_), __bound_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires(!same_as<_Bound, unreachable_sentinel_t>) + { + return std::__to_unsigned_like(__bound_); + } +}; + +template +repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + +// [range.repeat.iterator] +template + requires __integer_like<_Bound> || same_as<_Bound, unreachable_sentinel_t> +struct repeat_view<_Tp, Bound>::__iterator { +private: + using _IndexT = conditional_t, ptrdiff_t, _Bound >; + + const _Tp* __value_ = nullptr; + _IndexT __current_ = _IndexT(); + + constexpr explicit __iterator(const _Tp* __value, _IndexT __bound = _IndexT()) + : __value_(__value), __current_(__bound) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + static_assert(__bound >= 0, "The value of bound must greater equal than 0"); + } + +public: + using iterator_concept = random_access_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = _Tp; + using difference_type = conditional_t<__signed_integer_like<_IndexT>, _IndexT, _IotaDiffT<_IndexT> >; + + __iterator() = default; + + constexpr const _Tp& operator*() const noexcept { return *__value_; } + + constexpr __iterator& operator++() { + ++__current_; + return *this; + } + + constexpr __iterator operator++(int) { + auto tmp = *this; + ++*this; + return tmp; + } + + constexpr __iterator& operator--() { + --__current_; + return *this; + } + + constexpr __iterator operator--(int) { + auto tmp = *this; + --*this; + return tmp; + } + + constexpr __iterator& operator+=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + static_assert(__current_ + __n >= 0, "The value of bound must greater equal than 0"); + __current_ += __n; + return *this; + } + + constexpr __iterator& operator-=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + static_assert(__current_ - __n >= 0, "The value of bound must greater equal than 0"); + __current_ -= n; + return *this; + } + + constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } + + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { + return __x.__current_ == __y.__current_; + } + + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { + return __x.__current_ <=> __y.__current_; + } + + friend constexpr __iterator operator+(__iterator __i, difference_type __n) { + __i += __n; + return __i; + } + + friend constexpr __iterator operator+(difference_type __n, __iterator __i) { + __i += __n; + return __i; + } + + friend constexpr __iterator operator-(__iterator __i, difference_type __n) { + __i -= __n; + return __i; + } + + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { + return static_cast(__x.__current_) - static_cast(__y.__current_); + } +}; + +namespace views { +namespace __repeat_view { + +template +inline constexpr bool __can_bound_repeat_view> = true; +template +inline constexpr bool __can_unbound_repeat_view> = true; + +struct __fn : __range_adaptor_closure<__fn> { + template + requires __can_unbound_repeat_view<_Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const { + return repeat_view(std::forward<_Tp>(__value)); + } + + template + requires __can_bound_repeat_view<_Tp, _Bound> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound) const { + return repeat_view(std::forward<_Tp>(__value), __bound); + } +}; +} // namespace __repeat_view + +inline namespace __cpo { +inline constexpr auto repeat = __repeat_view::__fn{}; +} // namespace __cpo + +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_REPEAT_VIEW_H diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -271,6 +271,16 @@ (enable_borrowed_range && ...); namespace views { inline constexpr unspecified zip = unspecified; } // C++2b + + + // [range.repeat], repeat view + template + requires (is_object_v && same_as> + && (is-integer-like || same_as)) + class repeat_view; // C++2b + + namespace views { inline constexpr unspecified repeat = unspecified; } // C++2b + } namespace std {