diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -344,6 +344,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_ranges_join_with`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_ranges_repeat`` *unimplemented* + ------------------------------------------------- ----------------- ``__cpp_lib_ranges_slide`` *unimplemented* ------------------------------------------------- ----------------- ``__cpp_lib_ranges_starts_ends_with`` *unimplemented* diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -77,7 +77,7 @@ "`P2460R2 `__","LWG","Relax requirements on ``wchar_t`` to match existing practices","July 2022","","" "`P2465R3 `__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","","" "`P2467R1 `__","LWG","Support exclusive mode for ``fstreams``","July 2022","","" -"`P2474R2 `__","LWG","``views::repeat``","July 2022","","","|ranges|" +"`P2474R2 `__","LWG","``views::repeat``","July 2022","|Complete|","17.0","|ranges|" "`P2494R2 `__","LWG","Relaxing range adaptors to allow for move only types","July 2022","","","|ranges|" "`P2499R0 `__","LWG","``string_view`` range constructor should be ``explicit``","July 2022","|Complete|","16.0","|ranges|" "`P2502R2 `__","LWG","``std::generator``: Synchronous Coroutine Generator for Ranges","July 2022","","","|ranges|" 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 @@ -380,6 +380,7 @@ __fwd/hash.h __fwd/memory_resource.h __fwd/pair.h + __fwd/repeat_view.h __fwd/span.h __fwd/string.h __fwd/string_view.h @@ -543,6 +544,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/__fwd/repeat_view.h b/libcxx/include/__fwd/repeat_view.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__fwd/repeat_view.h @@ -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 +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_REPEAT_VIEW_H +#define _LIBCPP___FWD_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 <__type_traits/is_object.h> +#include <__type_traits/remove_cv.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +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; + +template +inline constexpr bool __is_repeat_specialization = false; + +template +inline constexpr bool __is_repeat_specialization> = true; + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___FWD_REPEAT_VIEW_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 @@ -16,6 +16,7 @@ #include <__concepts/convertible_to.h> #include <__config> #include <__functional/bind_back.h> +#include <__fwd/repeat_view.h> #include <__fwd/span.h> #include <__fwd/string_view.h> #include <__iterator/concepts.h> @@ -263,12 +264,49 @@ std::__to_unsigned_like(__dist - __clamped) );} +#if _LIBCPP_STD_VER >= 23 + // [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_specialization<_RawRange> && + sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept( + noexcept(repeat_view(*ranges::begin(__range), + ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype(repeat_view(*ranges::begin(__range), + ranges::distance(__range) - + std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { + return repeat_view(*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_specialization<_RawRange> && + !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _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)); } +#endif + // [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> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__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,224 @@ +// -*- 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 <__type_traits/is_object.h> +#include <__type_traits/remove_cv.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/piecewise_construct.h> +#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(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> { + class __iterator; + +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_sentinel = _Bound()) + : __value_(in_place, __value), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be greater equal than 0"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) + : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be 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_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), + __bound_(std::make_from_tuple<_Bound>(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<_Bound, 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<_Bound, unreachable_sentinel_t>) + { + return std::__to_unsigned_like(__bound_); + } + +private: + __copyable_box<_Tp> __value_; + _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); +}; + +template +repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + +// [range.repeat.iterator] +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<_Tp, _Bound>::__iterator { + friend class repeat_view; + + using _IndexT = conditional_t, ptrdiff_t, _Bound>; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) + : __value_(__value), __current_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ >= 0, "The value of bound must be 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 __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ + __n >= 0, "The value of bound must be greater equal than 0"); + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ - __n >= 0, "The value of bound must be 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 __iterator& __x, const __iterator& __y) { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { + return static_cast(__x.__current_) - static_cast(__y.__current_); + } + +private: + const _Tp* __value_ = nullptr; + _IndexT __current_ = _IndexT(); +}; + +// clang-format off +namespace views { +namespace __repeat { +struct __fn : __range_adaptor_closure<__fn> { + template + requires constructible_from, _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 constructible_from, _Tp, _Bound> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) + -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) + { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } +}; +} // namespace __repeat +// clang-format on + +inline namespace __cpo { +inline constexpr auto repeat = __repeat::__fn{}; +} // namespace __cpo + +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_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 @@ -17,6 +17,7 @@ #include <__concepts/convertible_to.h> #include <__config> #include <__functional/bind_back.h> +#include <__fwd/repeat_view.h> #include <__fwd/span.h> #include <__fwd/string_view.h> #include <__iterator/concepts.h> @@ -298,12 +299,41 @@ *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) ); } +#if _LIBCPP_STD_VER >= 23 + // [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_specialization<_RawRange> && sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const noexcept(noexcept( + repeat_view(*ranges::begin(__range), std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype(repeat_view(*ranges::begin(__range), + std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) { + return repeat_view(*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_specialization<_RawRange> && !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(repeat_view(*ranges::begin(__range), static_cast<_Dist>(__n)))) + -> decltype(repeat_view(*ranges::begin(__range), static_cast<_Dist>(__n))) { + return repeat_view(*ranges::begin(__range), static_cast<_Dist>(__n)); + } +#endif // [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> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__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 @@ -1301,6 +1301,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 @@ -252,6 +252,14 @@ 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> @@ -366,6 +374,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/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -145,6 +145,7 @@ __cpp_lib_ranges_chunk_by 202202L __cpp_lib_ranges_iota 202202L __cpp_lib_ranges_join_with 202202L +__cpp_lib_ranges_repeat 202207L __cpp_lib_ranges_slide 202202L __cpp_lib_ranges_starts_ends_with 202106L __cpp_lib_ranges_to_container 202202L @@ -409,6 +410,7 @@ // # define __cpp_lib_ranges_chunk_by 202202L // # define __cpp_lib_ranges_iota 202202L // # define __cpp_lib_ranges_join_with 202202L +// # define __cpp_lib_ranges_repeat 202207L // # define __cpp_lib_ranges_slide 202202L // # define __cpp_lib_ranges_starts_ends_with 202106L // # define __cpp_lib_ranges_to_container 202202L diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -412,6 +412,7 @@ #include <__fwd/hash.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/hash.h'}} #include <__fwd/memory_resource.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/memory_resource.h'}} #include <__fwd/pair.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/pair.h'}} +#include <__fwd/repeat_view.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/repeat_view.h'}} #include <__fwd/span.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/span.h'}} #include <__fwd/string.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/string.h'}} #include <__fwd/string_view.h> // expected-error@*:* {{use of private header from outside its module: '__fwd/string_view.h'}} @@ -574,6 +575,7 @@ #include <__ranges/rbegin.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/rbegin.h'}} #include <__ranges/ref_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/ref_view.h'}} #include <__ranges/rend.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/rend.h'}} +#include <__ranges/repeat_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/repeat_view.h'}} #include <__ranges/reverse_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/reverse_view.h'}} #include <__ranges/single_view.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/single_view.h'}} #include <__ranges/size.h> // expected-error@*:* {{use of private header from outside its module: '__ranges/size.h'}} diff --git a/libcxx/test/libcxx/ranges/range.factories/range.repeat.view/ctor.value.bound.verify.cpp b/libcxx/test/libcxx/ranges/range.factories/range.repeat.view/ctor.value.bound.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.factories/range.repeat.view/ctor.value.bound.verify.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +// constexpr explicit repeat_view(W&& value, Bound bound = Bound()); +// constexpr explicit repeat_view(const W& value, Bound bound = Bound()); + +#include + +#include "check_assertion.h" + +int main(int, char**) { + { + TEST_LIBCPP_ASSERT_FAILURE( + std::ranges::repeat_view(0, -1), "The value of bound must be greater equal than 0"); // expected-no-diagnostics + } + + return 0; +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp @@ -21,6 +21,7 @@ __cpp_lib_ranges_chunk 202202L [C++2b] __cpp_lib_ranges_chunk_by 202202L [C++2b] __cpp_lib_ranges_join_with 202202L [C++2b] + __cpp_lib_ranges_repeat 202207L [C++2b] __cpp_lib_ranges_slide 202202L [C++2b] __cpp_lib_ranges_zip 202110L [C++2b] */ @@ -50,6 +51,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -80,6 +85,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -110,6 +119,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -143,6 +156,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -206,6 +223,19 @@ # endif # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should be defined in c++2b" +# endif +# if __cpp_lib_ranges_repeat != 202207L +# error "__cpp_lib_ranges_repeat should have the value 202207L in c++2b" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined because it is unimplemented in libc++!" +# endif +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should be defined in c++2b" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.compile.pass.cpp @@ -19,6 +19,7 @@ __cpp_lib_apply 201603L [C++17] __cpp_lib_constexpr_tuple 201811L [C++20] __cpp_lib_make_from_tuple 201606L [C++17] + __cpp_lib_ranges_repeat 202207L [C++2b] __cpp_lib_ranges_zip 202110L [C++2b] __cpp_lib_tuple_element_t 201402L [C++14] __cpp_lib_tuples_by_type 201304L [C++14] @@ -41,6 +42,10 @@ # error "__cpp_lib_make_from_tuple should not be defined before c++17" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -67,6 +72,10 @@ # error "__cpp_lib_make_from_tuple should not be defined before c++17" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -105,6 +114,10 @@ # error "__cpp_lib_make_from_tuple should have the value 201606L in c++17" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -146,6 +159,10 @@ # error "__cpp_lib_make_from_tuple should have the value 201606L in c++20" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -187,6 +204,19 @@ # error "__cpp_lib_make_from_tuple should have the value 201606L in c++2b" # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should be defined in c++2b" +# endif +# if __cpp_lib_ranges_repeat != 202207L +# error "__cpp_lib_ranges_repeat should have the value 202207L in c++2b" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined because it is unimplemented in libc++!" +# endif +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should be defined in c++2b" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp @@ -23,6 +23,7 @@ __cpp_lib_forward_like 202207L [C++2b] __cpp_lib_integer_comparison_functions 202002L [C++20] __cpp_lib_integer_sequence 201304L [C++14] + __cpp_lib_ranges_repeat 202207L [C++2b] __cpp_lib_ranges_zip 202110L [C++2b] __cpp_lib_to_underlying 202102L [C++2b] __cpp_lib_tuples_by_type 201304L [C++14] @@ -62,6 +63,10 @@ # error "__cpp_lib_integer_sequence should not be defined before c++14" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -114,6 +119,10 @@ # error "__cpp_lib_integer_sequence should have the value 201304L in c++14" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -172,6 +181,10 @@ # error "__cpp_lib_integer_sequence should have the value 201304L in c++17" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -239,6 +252,10 @@ # error "__cpp_lib_integer_sequence should have the value 201304L in c++20" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should not be defined before c++2b" # endif @@ -309,6 +326,19 @@ # error "__cpp_lib_integer_sequence should have the value 201304L in c++2b" # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should be defined in c++2b" +# endif +# if __cpp_lib_ranges_repeat != 202207L +# error "__cpp_lib_ranges_repeat should have the value 202207L in c++2b" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined because it is unimplemented in libc++!" +# endif +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_ranges_zip # error "__cpp_lib_ranges_zip should be defined in c++2b" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -134,6 +134,7 @@ __cpp_lib_ranges_chunk_by 202202L [C++2b] __cpp_lib_ranges_iota 202202L [C++2b] __cpp_lib_ranges_join_with 202202L [C++2b] + __cpp_lib_ranges_repeat 202207L [C++2b] __cpp_lib_ranges_slide 202202L [C++2b] __cpp_lib_ranges_starts_ends_with 202106L [C++2b] __cpp_lib_ranges_to_container 202202L [C++2b] @@ -647,6 +648,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -1329,6 +1334,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -2176,6 +2185,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -3293,6 +3306,10 @@ # error "__cpp_lib_ranges_join_with should not be defined before c++2b" # endif +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined before c++2b" +# endif + # ifdef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should not be defined before c++2b" # endif @@ -4596,6 +4613,19 @@ # endif # endif +# if !defined(_LIBCPP_VERSION) +# ifndef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should be defined in c++2b" +# endif +# if __cpp_lib_ranges_repeat != 202207L +# error "__cpp_lib_ranges_repeat should have the value 202207L in c++2b" +# endif +# else // _LIBCPP_VERSION +# ifdef __cpp_lib_ranges_repeat +# error "__cpp_lib_ranges_repeat should not be defined because it is unimplemented in libc++!" +# endif +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_ranges_slide # error "__cpp_lib_ranges_slide should be defined in c++2b" 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,25 @@ test_small_range(std::views::iota(1, 8)); } +#if TEST_STD_VER >= 23 + // `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); + } +#endif + // 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 @@ -179,6 +179,26 @@ assert(result.size() == 3); } +#if TEST_STD_VER >= 23 + // `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); + } +#endif + // When the size of the input range `s` is shorter than `n`, only `s` elements are taken. { test_small_range(std::span(buf)); 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,67 @@ +//===----------------------------------------------------------------------===// +// +// 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 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); + } + { + std::ranges::repeat_view rv(0, 10); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 0); + } + { + const std::ranges::repeat_view rv(0, 1024); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 0); + } + { + std::ranges::repeat_view rv(42, 20); + std::same_as> decltype(auto) iter = rv.begin(); + assert(*iter == 42); + } + { + const std::ranges::repeat_view rv(42, 33); + 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,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 {}; + +// clang-format off +static_assert(std::same_as >); +static_assert(std::same_as())), std::ranges::repeat_view >); +static_assert(std::same_as())), std::ranges::repeat_view >); +static_assert(std::same_as >); +static_assert(std::same_as(), 1U)), std::ranges::repeat_view >); +static_assert(std::same_as(), 1UL)), std::ranges::repeat_view >); +// clang-format on + +int main(int, char**) { 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,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 + +// repeat_view() requires default_initializable = default; + +#include +#include +#include + +struct DefaultInt42 { + int __value_ = 42; +}; + +struct Int { + int __value_; + Int(int v) : __value_(v) {} +}; + +static_assert(std::default_initializable>); +static_assert(!std::default_initializable>); + +constexpr bool test() { + std::ranges::repeat_view rv; + 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,134 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// std::ranges::repeat_view requires P0960, but P0960 supported since clang 16. +// [P0960] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0960r3.html +// TODO LLVM18: remove this workaround +// XFAIL: clang-14, clang-15, apple-clang-14 + +// template +// requires constructible_from && constructible_from +// constexpr explicit repeat_view( +// piecewise_construct_t, tuple value_args, tuple bound_args = tuple<>{}); + +#include +#include +#include +#include +#include + +struct C {}; + +struct B { + int v_; +}; + +struct A { + int x_ = 111; + int y_ = 222; + + constexpr A() = default; + constexpr A(B b) : x_(b.v_), y_(b.v_ + 1) {} + constexpr A(int x, int y) : x_(x), y_(y) {} +}; + +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple<>, + std::tuple>); + +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(std::constructible_from, + std::piecewise_construct_t, + std::tuple<>, + std::tuple>); + +static_assert(!std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(!std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(!std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); +static_assert(!std::constructible_from, + std::piecewise_construct_t, + std::tuple, + std::tuple>); + +constexpr bool test() { + { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{}, std::tuple{3}); + assert(rv.size() == 3); + assert(rv[0].x_ == 111); + assert(rv[0].y_ == 222); + assert(std::ranges::next(rv.begin(), 3) == rv.end()); + } + { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{}, std::tuple{std::unreachable_sentinel}); + assert(rv[0].x_ == 111); + assert(rv[0].y_ == 222); + assert(std::ranges::next(rv.begin(), 300) != rv.end()); + } + { + 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()); + } + { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{1, 2}, std::tuple{std::unreachable_sentinel}); + assert(rv[0].x_ == 1); + assert(rv[0].y_ == 2); + assert(std::ranges::next(rv.begin(), 300) != rv.end()); + } + { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{B{11}}, std::tuple{3}); + assert(rv.size() == 3); + assert(rv[0].x_ == 11); + assert(rv[0].y_ == 12); + assert(std::ranges::next(rv.begin(), 3) == rv.end()); + } + { + std::ranges::repeat_view rv(std::piecewise_construct, std::tuple{B{10}}, std::tuple{std::unreachable_sentinel}); + assert(rv[0].x_ == 10); + assert(rv[0].y_ == 11); + assert(std::ranges::next(rv.begin(), 300) != 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,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 explicit repeat_view(W&& value, Bound bound = Bound()); +// constexpr explicit repeat_view(const W& value, Bound bound = Bound()); + +#include +#include +#include + +struct Empty {}; + +// Test explicit +static_assert(std::is_constructible_v, const Empty&>); +static_assert(std::is_constructible_v, Empty&&>); +static_assert(std::is_constructible_v, const Empty&>); +static_assert(std::is_constructible_v, Empty&&>); + +static_assert(!std::is_convertible_v>); +static_assert(!std::is_convertible_v>); +static_assert(!std::is_convertible_v>); +static_assert(!std::is_convertible_v>); + +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 + { + const 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,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 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); + static_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,64 @@ +//===----------------------------------------------------------------------===// +// +// 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::ranges::repeat_view r(42); + auto iter1 = r.begin(); + auto iter2 = iter1 + 1; + + assert(iter1 == iter1); + assert(!(iter1 == iter2)); + assert(iter2 == iter2); + + static_assert(std::same_as); + + assert((iter1 <=> iter2) == std::strong_ordering::less); + assert((iter1 <=> iter1) == std::strong_ordering::equal); + assert((iter2 <=> iter1) == std::strong_ordering::greater); + + static_assert(std::same_as iter2), std::strong_ordering>); + } + + { + using R = std::ranges::repeat_view; + static_assert(std::three_way_comparable>); + + std::ranges::repeat_view r(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,29 @@ +//===----------------------------------------------------------------------===// +// +// 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>; + static_assert(std::is_nothrow_default_constructible_v); + 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,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include + +constexpr bool test() { + std::ranges::repeat_view rv(10); + using Iter = std::ranges::iterator_t>; + 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); + 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/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,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 + { + using Iter = std::ranges::iterator_t>; + 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 + { + using Iter = std::ranges::iterator_t>; + 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 + { + using Iter = std::ranges::iterator_t>; + 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,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 + +// 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); + using Iter = std::ranges::iterator_t>; + auto iter1 = v.begin(); + auto iter2 = v.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == iter2 + 5); + assert(5 + iter1 != iter2); + assert(5 + iter1 == 5 + iter2); + assert(2 + iter1 == iter2 + 2); + assert(3 + iter1 == iter2 + 3); + + 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/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,38 @@ +//===----------------------------------------------------------------------===// +// +// 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); + using Iter = std::ranges::iterator_t>; + 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::same_as); + assert(std::addressof(iter2) == std::addressof(iter2 += 5)); + + 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,37 @@ +//===----------------------------------------------------------------------===// +// +// 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(); + const int& val = *iter; + for (int i = 0; i < 100; ++i, ++iter) { + assert(*iter == 31); + assert(std::addressof(*iter) == std::addressof(val)); + } + + static_assert(noexcept(*iter)); + 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,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 auto size() const requires see below; + +#include +#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()); + } + + 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,55 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// views::repeat + +#include +#include +#include + +struct NonCopyable { + NonCopyable(NonCopyable&) = delete; +}; + +struct NonDefaultCtor { + NonDefaultCtor(int) {} +}; + +struct Empty {}; + +// Tp is_object +static_assert(std::is_invocable_v); +static_assert(!std::is_invocable_v); + +// _Bound is semiregular, integer like or std::unreachable_sentinel_t +static_assert(!std::is_invocable_v); +static_assert(!std::is_invocable_v); +static_assert(!std::is_invocable_v); +static_assert(std::is_invocable_v); + +// Tp is copy_constructible +static_assert(!std::is_invocable_v); + +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 @@ -562,6 +562,11 @@ "values": { "c++2b": 202202 }, "headers": ["ranges"], "unimplemented": True, + }, { + "name": "__cpp_lib_ranges_repeat", + "values": { "c++2b": 202207 }, + "headers": ["ranges", "tuple", "utility"], + "unimplemented": True, }, { "name": "__cpp_lib_ranges_slide", "values": { "c++2b": 202202 },