diff --git a/libcxx/docs/Status/RangesViews.csv b/libcxx/docs/Status/RangesViews.csv --- a/libcxx/docs/Status/RangesViews.csv +++ b/libcxx/docs/Status/RangesViews.csv @@ -22,7 +22,7 @@ ,,,, ,,,, ,,,, -C++23,`repeat `_,Unassigned,No patch yet,Not started +C++23,`repeat `_,Yrong,`D141699 `_,✅ C++23,`cartesian_product `_,Unassigned,No patch yet,Not started C++23,`zip `_,Hui Xie,`D122806 `_,✅ C++23,`zip_transform `_,Hui Xie,No patch yet,Not started diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -526,6 +526,7 @@ __ranges/rbegin.h __ranges/ref_view.h __ranges/rend.h + __ranges/repeat_view.h __ranges/reverse_view.h __ranges/single_view.h __ranges/size.h diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -30,6 +30,7 @@ #include <__ranges/iota_view.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> @@ -144,6 +145,12 @@ template inline constexpr bool __is_empty_view> = true; +template +inline constexpr bool __is_repeat_view = false; + +template +inline constexpr bool __is_repeat_view> = true; + template inline constexpr bool __is_passthrough_specialization = false; @@ -153,8 +160,8 @@ template inline constexpr bool __is_passthrough_specialization> = true; -template -inline constexpr bool __is_passthrough_specialization> = true; +template +inline constexpr bool __is_passthrough_specialization> = true; template inline constexpr bool __is_passthrough_specialization> = @@ -263,12 +270,44 @@ std::__to_unsigned_like(dist - clamped) );} + // [range.drop.overview]: the `repeat_view` "_RawRange models sized_range" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (!__is_empty_view<_RawRange> && + __is_repeat_view<_RawRange> && + sized_range<_RawRange>) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept( + noexcept(views::repeat(*ranges::begin(__range), + ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype(views::repeat(*ranges::begin(__range), + ranges::distance(__range) - + std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { + return views::repeat(*ranges::begin(__range), + ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); + } + + // [range.drop.overview]: the `repeat_view` "otherwise" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (!__is_empty_view<_RawRange> && + __is_repeat_view<_RawRange> && + !sized_range<_RawRange>) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Np&&) const + noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) + -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) + { return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); } + // [range.drop.overview]: the "otherwise" case. template > _Np, class _RawRange = remove_cvref_t<_Range>> // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. - requires (!(__is_empty_view<_RawRange> || + requires (!(__is_empty_view<_RawRange> || __is_repeat_view<_RawRange> || (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || 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,249 @@ +// -*- 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/same_as.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/unreachable_sentinel.h> +#include <__memory/addressof.h> +#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 + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template + requires __integer_like<_BoundSentinel> || same_as<_BoundSentinel, unreachable_sentinel_t> +class __repeat_view_iterator; + +template + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like<_BoundSentinel> || same_as<_BoundSentinel, unreachable_sentinel_t>)) +class repeat_view : public view_interface> { + using __iterator = __repeat_view_iterator<_Tp, _BoundSentinel>; + + template + requires __integer_like<_BoundSentinelType> || same_as<_BoundSentinelType, unreachable_sentinel_t> + friend class __repeat_view_iterator; + +public: + _LIBCPP_HIDE_FROM_ABI repeat_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, + _BoundSentinel __bound_sentinel = _BoundSentinel()) + : __value_(std::in_place, __value), __bound_(__bound_sentinel) { + if constexpr (!same_as<_BoundSentinel, 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, + _BoundSentinel __bound_sentinel = _BoundSentinel()) + : __value_(std::in_place, std::move(__value)), __bound_(__bound_sentinel) { + if constexpr (!same_as<_BoundSentinel, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must greater equal than 0"); + } + + template + requires constructible_from<_Tp, _TpArgs...> && constructible_from<_BoundSentinel, _BoundSentinelArgs...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( + piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundSentinelArgs...> __bound_args = tuple<>{}) + : __value_(std::in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), + __bound_(std::make_from_tuple<_BoundSentinel>(std::move(__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<_BoundSentinel, unreachable_sentinel_t>) + { + 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<_BoundSentinel, unreachable_sentinel_t>) + { + return std::__to_unsigned_like(__bound_); + } + +private: + __copyable_box<_Tp> __value_ = __copyable_box<_Tp>(std::in_place, _Tp()); + _LIBCPP_NO_UNIQUE_ADDRESS _BoundSentinel __bound_ = _BoundSentinel(); +}; + +template +repeat_view(_Tp, _BoundSentinel) -> repeat_view<_Tp, _BoundSentinel>; + +// [range.repeat.iterator] +template + requires __integer_like<_BoundSentinel> || same_as<_BoundSentinel, unreachable_sentinel_t> +class __repeat_view_iterator { + template + requires(is_object_v<_ValueType> && same_as<_ValueType, remove_cv_t<_ValueType>> && + (__integer_like<_BoundSentinelType> || same_as<_BoundSentinelType, unreachable_sentinel_t>)) + friend class repeat_view; + + using _IndexT = conditional_t, ptrdiff_t, _BoundSentinel >; + + constexpr explicit __repeat_view_iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) + : __value_(__value), __current_(__bound_sentinel) { + if constexpr (!same_as<_BoundSentinel, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ >= 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> >; + + _LIBCPP_HIDE_FROM_ABI __repeat_view_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator operator++(int) { + auto tmp = *this; + ++*this; + return tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator& operator--() { + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator operator--(int) { + auto tmp = *this; + --*this; + return tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator& operator+=(difference_type __n) { + if constexpr (!same_as<_BoundSentinel, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ + __n >= 0, "The value of bound must greater equal than 0"); + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __repeat_view_iterator& operator-=(difference_type __n) { + if constexpr (!same_as<_BoundSentinel, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ - __n >= 0, "The value of bound must greater equal than 0"); + __current_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __repeat_view_iterator& __x, const __repeat_view_iterator& __y) { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto + operator<=>(const __repeat_view_iterator& __x, const __repeat_view_iterator& __y) { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __repeat_view_iterator + operator+(__repeat_view_iterator __i, difference_type __n) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __repeat_view_iterator + operator+(difference_type __n, __repeat_view_iterator __i) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __repeat_view_iterator + operator-(__repeat_view_iterator __i, difference_type __n) { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type + operator-(const __repeat_view_iterator& __x, const __repeat_view_iterator& __y) { + return static_cast(__x.__current_) - static_cast(__y.__current_); + } + +private: + const _Tp* __value_ = nullptr; + _IndexT __current_ = _IndexT(); +}; + +namespace views { +namespace __repeat { + +template +concept __can_unbound_repeat_view = requires { repeat_view(std::declval<_Tp>()); }; + +template +concept __can_bound_repeat_view = requires { repeat_view(std::declval<_Tp>(), std::declval<_BoundSentinel>()); }; + +struct __fn : __range_adaptor_closure<__fn> { + template + requires __can_unbound_repeat_view<_Tp> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) + -> decltype(ranges::repeat_view(std::forward<_Tp>(__value))) { + return ranges::repeat_view(std::forward<_Tp>(__value)); + } + + template + requires __can_bound_repeat_view<_Tp, _BoundSentinel> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto + operator()(_Tp&& __value, _BoundSentinel&& __bound_sentinel) const noexcept( + noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_BoundSentinel>(__bound_sentinel)))) + -> decltype(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_BoundSentinel>(__bound_sentinel))) { + return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_BoundSentinel>(__bound_sentinel)); + } +}; +} // namespace __repeat + +inline namespace __cpo { +inline constexpr auto repeat = __repeat::__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/take_view.h b/libcxx/include/__ranges/take_view.h --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -31,6 +31,7 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/iota_view.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> @@ -213,8 +214,14 @@ template inline constexpr bool __is_iota_specialization = false; -template -inline constexpr bool __is_iota_specialization> = true; +template +inline constexpr bool __is_iota_specialization> = true; + +template +inline constexpr bool __is_repeat_view = false; + +template +inline constexpr bool __is_repeat_view> = true; template struct __passthrough_type; @@ -298,12 +305,37 @@ *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) ); } + // [range.take.overview]: the `repeat_view` "_RawRange models sized_range" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(!__is_empty_view<_RawRange> && __is_repeat_view<_RawRange> && sized_range<_RawRange>) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept( + views::repeat(*ranges::begin(__range), std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype(views::repeat(*ranges::begin(__range), + std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { + return views::repeat(*ranges::begin(__range), std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); + } + + // [range.take.overview]: the `repeat_view` "otherwise" case. + template > _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(!__is_empty_view<_RawRange> && __is_repeat_view<_RawRange> && !sized_range<_RawRange>) + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*ranges::begin(__range), static_cast<_Dist>(__n)))) + -> decltype(views::repeat(*ranges::begin(__range), static_cast<_Dist>(__n))) { + return views::repeat(*ranges::begin(__range), static_cast<_Dist>(__n)); + } + // [range.take.overview]: the "otherwise" case. template > _Np, class _RawRange = remove_cvref_t<_Range>> // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. - requires (!(__is_empty_view<_RawRange> || + requires (!(__is_empty_view<_RawRange> || __is_repeat_view<_RawRange> || (__is_iota_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1269,6 +1269,7 @@ module rbegin { private header "__ranges/rbegin.h" } module ref_view { private header "__ranges/ref_view.h" } module rend { private header "__ranges/rend.h" } + module repeat_view { private header "__ranges/repeat_view.h" } module reverse_view { private header "__ranges/reverse_view.h" } module single_view { private header "__ranges/single_view.h" } module size { private header "__ranges/size.h" } diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -250,6 +250,15 @@ template inline constexpr bool enable_borrowed_range> = true; + + // [range.repeat], repeat view + template + requires (is_object_v && same_as> + && (is-integer-like || same_as)) + class repeat_view; + + namespace views { inline constexpr unspecified repeat = unspecified; } + // [range.join], join view template requires view && input_range> @@ -364,6 +373,7 @@ #include <__ranges/rbegin.h> #include <__ranges/ref_view.h> #include <__ranges/rend.h> +#include <__ranges/repeat_view.h> #include <__ranges/reverse_view.h> #include <__ranges/single_view.h> #include <__ranges/size.h> diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/adaptor.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop/adaptor.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/adaptor.pass.cpp @@ -220,6 +220,23 @@ test_small_range(std::views::iota(1, 8)); } + // `views::drop(repeat_view, n)` returns an `repeat_view` when repeat_view models sized_range. + { + auto repeat = std::ranges::repeat_view(1, 8); + using Result = std::ranges::repeat_view; + std::same_as decltype(auto) result = repeat | std::views::drop(3); + assert(result.size() == 5); + assert(*result.begin() == 1); + } + + // `views::drop(repeat_view, n)` returns an `repeat_view` when repeat_view not models sized_range. + { + auto repeat = std::ranges::repeat_view(1); + using Result = std::ranges::repeat_view; + std::same_as decltype(auto) result = repeat | std::views::drop(3); + static_assert(std::same_as); + } + // Test that it's possible to call `std::views::drop` with any single argument as long as the resulting closure is // never invoked. There is no good use case for it, but it's valid. { diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/adaptor.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.take/adaptor.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.take/adaptor.pass.cpp @@ -187,6 +187,24 @@ test_small_range(std::views::iota(1, 8)); } + // `views::take(repeat_view, n)` returns an `repeat_view` when repeat_view models sized_range. + { + auto repeat = std::ranges::repeat_view(1, 8); + using Result = std::ranges::repeat_view; + std::same_as decltype(auto) result = repeat | std::views::take(3); + assert(result.size() == 3); + assert(*result.begin() == 1); + } + + // `views::take(repeat_view, n)` returns an `repeat_view` when repeat_view not models sized_range. + { + auto repeat = std::ranges::repeat_view(1); + using Result = std::ranges::repeat_view; + std::same_as decltype(auto) result = repeat | std::views::take(3); + assert(result.size() == 3); + assert(*result.begin() == 1); + } + // Test that it's possible to call `std::views::take` with any single argument as long as the resulting closure is // never invoked. There is no good use case for it, but it's valid. { diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/begin.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/begin.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iterator begin() const; + +#include +#include +#include + +constexpr bool test() { + { + std::ranges::repeat_view rv(0); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 0); + } + { + const std::ranges::repeat_view rv(0); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 0); + } + { + std::ranges::repeat_view rv(42); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 42); + } + { + const std::ranges::repeat_view rv(42); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 42); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctad.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctad.compile.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template +// repeat_view(W, Bound) -> repeat_view; + +#include +#include +#include + +struct Empty {}; + +constexpr bool test() { + static_assert(std::same_as< decltype(std::ranges::repeat_view(Empty())), std::ranges::repeat_view >); + + static_assert( + std::same_as< decltype(std::ranges::repeat_view(std::declval())), std::ranges::repeat_view >); + + static_assert( + std::same_as< decltype(std::ranges::repeat_view(std::declval())), std::ranges::repeat_view >); + + static_assert(std::same_as< decltype(std::ranges::repeat_view(Empty(), 1)), std::ranges::repeat_view >); + + static_assert(std::same_as< decltype(std::ranges::repeat_view(std::declval(), 1U)), + std::ranges::repeat_view >); + + static_assert(std::same_as< decltype(std::ranges::repeat_view(std::declval(), 1UL)), + std::ranges::repeat_view >); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.default.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// repeat_view() requires default_initializable = default; + +#include +#include +#include + +struct DefaultInt42 { + int __value_ = 42; +}; + +constexpr bool test() { + std::ranges::repeat_view rv(DefaultInt42{}); + assert((*rv.begin()).__value_ == 42); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.piecewise.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.piecewise.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.piecewise.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// template +// requires constructible_from && constructible_from +// constexpr explicit repeat_view( +// piecewise_construct_t, tuple value_args, tuple bound_args = tuple<>{}); + +#include +#include +#include + +struct A { + int x_; + int y_; +}; + +constexpr bool test() { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{1, 2}, std::tuple{3}); + assert(rv.size() == 3); + assert(rv[0].x_ == 1); + assert(rv[0].y_ == 2); + assert(std::ranges::next(rv.begin(), 3) == rv.end()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.value.bound.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/ctor.value.bound.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr explicit repeat_view(W&& value, Bound bound = Bound()); +// constexpr explicit repeat_view(const W& value, Bound bound = Bound()); + +#include +#include +#include + +struct Empty {}; + +constexpr bool test() { + // Move && unbound && default argument + { + std::ranges::repeat_view rv(Empty{}); + assert(std::ranges::next(rv.begin(), 10) != rv.end()); + } + + // Move && unbound && specific argument + { + std::ranges::repeat_view rv(Empty{}, std::unreachable_sentinel); + assert(std::ranges::next(rv.begin(), 10) != rv.end()); + } + + // Move && bound && default argument + { + std::ranges::repeat_view rv(Empty{}); + assert(rv.begin() == rv.end()); + } + + // Move && bound && specific argument + { + std::ranges::repeat_view rv(Empty{}, 10); + assert(std::ranges::next(rv.begin(), 10) == rv.end()); + } + + // Copy && unbound && default argument + { + Empty e; + std::ranges::repeat_view rv(e); + assert(std::ranges::next(rv.begin(), 10) != rv.end()); + } + + // Copy && unbound && specific argument + { + Empty e; + std::ranges::repeat_view rv(e, std::unreachable_sentinel); + assert(std::ranges::next(rv.begin(), 10) != rv.end()); + } + + // Copy && bound && default argument + { + Empty e; + std::ranges::repeat_view rv(e); + assert(rv.begin() == rv.end()); + } + + // Copy && bound && specific argument + { + Empty e; + std::ranges::repeat_view rv(e, 10); + assert(std::ranges::next(rv.begin(), 10) == rv.end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/end.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/end.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr auto end() const; +// constexpr iterator end() const requires same_as; + +#include +#include +#include +#include + +constexpr bool test() { + // bound + { + std::ranges::repeat_view rv(0, 10); + assert(std::ranges::next(rv.begin(), 10) == rv.end()); + std::same_as> decltype(auto) iter = rv.end(); + static_assert(std::same_as); + } + + // unbound + { + std::ranges::repeat_view rv(0); + assert(std::ranges::next(rv.begin(), 10) != rv.end()); + static_assert(std::same_as); + //ASSERT_NOEXCEPT(rv.end()); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/compare.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/compare.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// repeat_view::::operator{==,<=>} + +#include +#include +#include + +constexpr bool test() { + { + using R = std::ranges::repeat_view; + static_assert(std::three_way_comparable>); + + std::same_as auto r = std::views::repeat(42); + auto iter1 = r.begin(); + auto iter2 = iter1 + 1; + + assert(iter1 == iter1); + assert(!(iter1 == iter2)); + assert(iter2 == iter2); + + assert((iter1 <=> iter2) == std::strong_ordering::less); + assert((iter1 <=> iter1) == std::strong_ordering::equal); + assert((iter2 <=> iter1) == std::strong_ordering::greater); + } + + { + using R = std::ranges::repeat_view; + static_assert(std::three_way_comparable>); + + std::same_as auto r = std::views::repeat(42, 10); + auto iter1 = r.begin(); + auto iter2 = iter1 + 1; + + assert(iter1 == iter1); + assert(!(iter1 == iter2)); + assert(iter2 == iter2); + + assert((iter1 <=> iter2) == std::strong_ordering::less); + assert((iter1 <=> iter1) == std::strong_ordering::equal); + assert((iter2 <=> iter1) == std::strong_ordering::greater); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/ctor.default.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// iterator() = default; + +#include + +constexpr bool test() { + using Iter = std::ranges::iterator_t>; + Iter iter; + (void)iter; + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/decrement.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/decrement.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr iterator& operator--(); +// constexpr iterator operator--(int); + +#include +#include + +constexpr bool test() { + std::ranges::repeat_view rv(10); + auto iter1 = rv.begin() + 10; + auto iter2 = rv.begin() + 10; + + assert(iter1 == iter2); + assert(iter1-- == iter2--); + assert(--iter1 == --iter2); + assert(iter1-- != --iter2); + assert(iter1 == iter2); + assert(--iter1 != iter2--); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert(std::is_reference_v); + + static_assert(std::same_as, decltype(iter2--)>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/increment.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/increment.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr iterator& operator++(); +// constexpr void operator++(int); + +#include +#include + +constexpr bool test() { + std::ranges::repeat_view rv(10); + auto iter1 = rv.begin(); + auto iter2 = rv.begin(); + + assert(iter1 == iter2); + assert(iter1++ == iter2++); + assert(++iter1 == ++iter2); + assert(iter1++ != ++iter2); + assert(iter1 == iter2); + assert(++iter1 != iter2++); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert(std::is_reference_v); + + static_assert(std::same_as, decltype(iter2++)>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/member_typedefs.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/member_typedefs.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/member_typedefs.compile.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// Test iterator category and iterator concepts. + +// using index-type = conditional_t, ptrdiff_t, Bound>; +// using iterator_concept = random_access_iterator_tag; +// using iterator_category = random_access_iterator_tag; +// using value_type = W; +// using difference_type = conditional_t, index-type, IOTA-DIFF-T(index-type)>; + +#include +#include +#include +#include + +constexpr bool test() { + // unbound + { + const std::ranges::repeat_view v(0); + using Iter = decltype(v.begin()); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::is_signed_v); + } + + // bound && signed bound sentinel + { + const std::ranges::repeat_view v(0, 10); + using Iter = decltype(v.begin()); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::is_signed_v); + static_assert(sizeof(Iter::difference_type) >= sizeof(long)); + } + + // bound && unsigned bound sentinel + { + const std::ranges::repeat_view v(0); + using Iter = decltype(v.begin()); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + + // If we're compiling for 32 bit or windows, int and long are the same size, so long long is the correct difference type. +#if INTPTR_MAX == INT32_MAX || defined(_WIN32) + static_assert(std::same_as); +#else + static_assert(std::same_as); +#endif + static_assert(std::is_signed_v); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// friend constexpr iterator operator-(iterator i, difference_type n); +// friend constexpr difference_type operator-(const iterator& x, const iterator& y); + +#include +#include +#include +#include + +constexpr bool test() { + // - difference_type + { + std::ranges::repeat_view v(0); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 10); + assert(iter1 == iter2); + assert(iter1 - 5 != iter2); + assert(iter1 - 5 == std::ranges::prev(iter2, 5)); + + static_assert(!std::is_reference_v); + } + + // - + { + // unbound + { + std::ranges::repeat_view v(0); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 5); + assert(iter1 - iter2 == 5); + static_assert(std::same_as); + } + + // bound && signed bound sentinel + { + std::ranges::repeat_view v(0, 20); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 5); + assert(iter1 - iter2 == 5); + static_assert(std::same_as); + } + + // bound && unsigned bound sentinel + { + std::ranges::repeat_view v(0, 20); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 5); + assert(iter1 - iter2 == 5); +#if INTPTR_MAX == INT32_MAX || defined(_WIN32) + static_assert(std::same_as); +#else + static_assert(std::same_as); +#endif + } + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus_eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/minus_eq.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr iterator& operator-=(difference_type n); + +#include +#include +#include + +constexpr bool test() { + std::ranges::repeat_view v(10); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 10); + assert(iter1 == iter2); + iter1 -= 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::prev(iter2, 5)); + + static_assert(std::is_reference_v); + + return true; +} + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// friend constexpr iterator operator+(iterator i, difference_type n); +// friend constexpr iterator operator+(difference_type n, iterator i); + +#include +#include +#include + +constexpr bool test() { + std::ranges::repeat_view v(10); + auto iter1 = v.begin(); + auto iter2 = v.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == std::ranges::next(iter2, 5)); + assert(5 + iter1 != iter2); + assert(5 + iter1 == 5 + iter2); + assert(2 + iter1 == iter2 + 2); + assert(3 + iter1 == std::ranges::next(iter2, 3)); + + static_assert(!std::is_reference_v); + static_assert(!std::is_reference_v); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus_eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/plus_eq.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr iterator& operator+=(difference_type n); + +#include +#include +#include + +constexpr bool test() { + std::ranges::repeat_view v(10); + auto iter1 = std::next(v.begin(), 10); + auto iter2 = std::next(v.begin(), 10); + assert(iter1 == iter2); + iter1 += 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/star.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/star.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const W & operator*() const noexcept; + +#include +#include +#include + +constexpr bool test() { + std::ranges::repeat_view v(31); + auto iter = v.begin(); + for (int i = 0; i < 100; ++i, ++iter) + assert(*iter == 31); + + static_assert(noexcept(*iter)); + static_assert(std::is_reference_v); + static_assert(std::same_as); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/subscript.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/iterator/subscript.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// constexpr const W & operator[](difference_type n) const noexcept; + +#include +#include +#include + +constexpr bool test() { + std::ranges::repeat_view v(31); + auto iter = v.begin(); + for (int i = 0; i < 100; ++i) + assert(iter[i] == 31); + + static_assert(noexcept(iter[0])); + static_assert(std::is_reference_v); + static_assert(std::same_as); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/size.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/size.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// constexpr auto size() const requires see below; + +#include +#include +#include +#include + +template +concept has_size = requires(T&& view) { + { std::forward(view).size() }; + }; + +static_assert(has_size>); +static_assert(!has_size>); +static_assert(!has_size>); + +constexpr bool test() { + { + std::ranges::repeat_view rv(10, 20); + assert(rv.size() == 20); + } + + { + std::ranges::repeat_view rv(10, std::numeric_limits::max()); + assert(rv.size() == std::numeric_limits::max()); + } + + { + std::ranges::repeat_view rv(10, -1); + assert(rv.size() == std::numeric_limits::max()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.repeat.view/views_repeat.pass.cpp b/libcxx/test/std/ranges/range.factories/range.repeat.view/views_repeat.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.repeat.view/views_repeat.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// views::repeat + +#include +#include +#include + +constexpr bool test() { + assert(*std::views::repeat(33).begin() == 33); + assert(*std::views::repeat(33, 10).begin() == 33); + static_assert(std::same_as>); + static_assert(std::same_as>); + static_assert(std::same_as); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -572,6 +572,11 @@ "unimplemented": True, }, { "name": "__cpp_lib_ranges_zip", + "values": { "c++2b": 202207 }, + "headers": ["ranges", "tuple", "utility"], + "unimplemented": True, + }, { + "name": "__cpp_lib_ranges_repeat", "values": { "c++2b": 202110 }, "headers": ["ranges", "tuple", "utility"], "unimplemented": True,