diff options
Diffstat (limited to 'libcxx')
91 files changed, 3695 insertions, 357 deletions
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index cade192..15bf46d 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -38,6 +38,7 @@ What's New in Libc++ 22.0.0? Implemented Papers ------------------ +- P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index e5b2dcf..189f845 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -170,7 +170,7 @@ "`LWG3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","2022-07 (Virtual)","|Complete|","16","" "`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20","" "`LWG3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15","" -"`LWG3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","","" +"`LWG3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","|Complete|","22","" "`LWG3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","2022-07 (Virtual)","|Complete|","16","" "`LWG3704 <https://wg21.link/LWG3704>`__","LWG 2059 added overloads that might be ill-formed for sets","2022-07 (Virtual)","","","" "`LWG3705 <https://wg21.link/LWG3705>`__","Hashability shouldn't depend on basic_string's allocator","2022-07 (Virtual)","|Complete|","16","" @@ -222,7 +222,7 @@ "`LWG3765 <https://wg21.link/LWG3765>`__","``const_sentinel`` should be constrained","2022-11 (Kona)","","","" "`LWG3766 <https://wg21.link/LWG3766>`__","``view_interface::cbegin`` is underconstrained","2022-11 (Kona)","","","" "`LWG3770 <https://wg21.link/LWG3770>`__","``const_sentinel_t`` is missing","2022-11 (Kona)","","","" -"`LWG3773 <https://wg21.link/LWG3773>`__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","","","" +"`LWG3773 <https://wg21.link/LWG3773>`__","``views::zip_transform`` still requires ``F`` to be ``copy_constructible`` when empty pack","2022-11 (Kona)","|Complete|","22","" "`LWG3774 <https://wg21.link/LWG3774>`__","``<flat_set>`` should include ``<compare>``","2022-11 (Kona)","","","" "`LWG3775 <https://wg21.link/LWG3775>`__","Broken dependencies in the ``Cpp17Allocator`` requirements","2022-11 (Kona)","","","" "`LWG3778 <https://wg21.link/LWG3778>`__","``vector<bool>`` missing exception specifications","2022-11 (Kona)","|Complete|","3.7","" @@ -234,7 +234,7 @@ "`LWG3792 <https://wg21.link/LWG3792>`__","``__cpp_lib_constexpr_algorithms`` should also be defined in ``<utility>``","2022-11 (Kona)","|Complete|","16","" "`LWG3795 <https://wg21.link/LWG3795>`__","Self-move-assignment of ``std::future`` and ``std::shared_future`` have unimplementable postconditions","2022-11 (Kona)","","","" "`LWG3796 <https://wg21.link/LWG3796>`__","``movable-box`` as member should use ``default-initialization`` instead of ``copy-initialization``","2022-11 (Kona)","","","" -"`LWG3798 <https://wg21.link/LWG3798>`__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``join_with_view``, ``zip_transform_view``, and ``adjacent_transform_view`` haven't been done yet since these types aren't implemented yet" +"`LWG3798 <https://wg21.link/LWG3798>`__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``adjacent_transform_view`` hasn't been done yet since this type isn't implemented yet" "`LWG3801 <https://wg21.link/LWG3801>`__","``cartesian_product_view::iterator::distance-from`` ignores the size of last underlying range","2022-11 (Kona)","","","" "`LWG3814 <https://wg21.link/LWG3814>`__","Add freestanding items requested by NB comments","2022-11 (Kona)","","","" "`LWG3816 <https://wg21.link/LWG3816>`__","``flat_map`` and ``flat_multimap`` should impose sequence container requirements","2022-11 (Kona)","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 25b567df..cd6583c 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -737,6 +737,7 @@ set(files __ranges/transform_view.h __ranges/view_interface.h __ranges/views.h + __ranges/zip_transform_view.h __ranges/zip_view.h __split_buffer __std_mbstate_t.h @@ -780,7 +781,6 @@ set(files __tuple/make_tuple_types.h __tuple/sfinae_helpers.h __tuple/tuple_element.h - __tuple/tuple_indices.h __tuple/tuple_like.h __tuple/tuple_like_ext.h __tuple/tuple_like_no_subrange.h diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h index 596cce0..def9e4c 100644 --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -83,15 +83,14 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_w template <class _Ti, class... _Uj, size_t... _Indx> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> -__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { +__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __index_sequence<_Indx...>) { return __ti(std::forward<_Uj>(std::get<_Indx>(__uj))...); } template <class _Ti, class... _Uj, __enable_if_t<is_bind_expression<_Ti>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...> __mu(_Ti& __ti, tuple<_Uj...>& __uj) { - typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices; - return std::__mu_expand(__ti, __uj, __indices()); + return std::__mu_expand(__ti, __uj, __make_index_sequence<sizeof...(_Uj)>()); } template <bool _IsPh, class _Ti, class _Uj> @@ -191,7 +190,7 @@ struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> { template <class _Fp, class _BoundArgs, size_t... _Indx, class _Args> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type -__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) { +__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __index_sequence<_Indx...>, _Args&& __args) { return std::__invoke(__f, std::__mu(std::get<_Indx>(__bound_args), __args)...); } @@ -205,8 +204,6 @@ private: _Fd __f_; _Td __bound_args_; - typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; - public: template < class _Gp, @@ -219,14 +216,22 @@ public: template <class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&&... __args) { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence<sizeof...(_BoundArgs)>(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } template <class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type operator()(_Args&&... __args) const { - return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); + return std::__apply_functor( + __f_, + __bound_args_, + __make_index_sequence<sizeof...(_BoundArgs)>(), + tuple<_Args&&...>(std::forward<_Args>(__args)...)); } }; diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index 1b8711f..6e7a9af 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -135,10 +135,10 @@ public: piecewise_construct, __transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(), std::move(__x), - typename __make_tuple_indices<sizeof...(_Args1)>::type{}), + make_index_sequence<sizeof...(_Args1)>()), __transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(), std::move(__y), - typename __make_tuple_indices<sizeof...(_Args2)>::type{})); + make_index_sequence<sizeof...(_Args2)>())); } template <class _T1, class _T2> @@ -194,20 +194,20 @@ public: private: template <class... _Args, size_t... _Is> _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...> - __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, index_sequence<_Is...>) { return std::forward_as_tuple(std::get<_Is>(std::move(__t))...); } template <class... _Args, size_t... _Is> _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...> - __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, index_sequence<_Is...>) { using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>; return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...); } template <class... _Args, size_t... _Is> _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&> - __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) { + __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, index_sequence<_Is...>) { using _Tup = tuple<_Args&&..., polymorphic_allocator&>; return _Tup(std::get<_Is>(std::move(__t))..., *this); } diff --git a/libcxx/include/__mutex/once_flag.h b/libcxx/include/__mutex/once_flag.h index 3306449..e384c15 100644 --- a/libcxx/include/__mutex/once_flag.h +++ b/libcxx/include/__mutex/once_flag.h @@ -13,9 +13,9 @@ #include <__functional/invoke.h> #include <__memory/addressof.h> #include <__memory/shared_count.h> // __libcpp_acquire_load -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_size.h> #include <__utility/forward.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include <cstdint> #ifndef _LIBCPP_CXX03_LANG @@ -87,15 +87,12 @@ class __call_once_param { public: _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {} - _LIBCPP_HIDE_FROM_ABI void operator()() { - typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _Index; - __execute(_Index()); - } + _LIBCPP_HIDE_FROM_ABI void operator()() { __execute(__make_index_sequence<tuple_size<_Fp>::value>()); } private: template <size_t... _Indices> - _LIBCPP_HIDE_FROM_ABI void __execute(__tuple_indices<_Indices...>) { - std::__invoke(std::get<0>(std::move(__f_)), std::get<_Indices>(std::move(__f_))...); + _LIBCPP_HIDE_FROM_ABI void __execute(__index_sequence<_Indices...>) { + std::__invoke(std::get<_Indices>(std::move(__f_))...); } }; diff --git a/libcxx/include/__ranges/zip_transform_view.h b/libcxx/include/__ranges/zip_transform_view.h new file mode 100644 index 0000000..07aa182f --- /dev/null +++ b/libcxx/include/__ranges/zip_transform_view.h @@ -0,0 +1,357 @@ +// -*- 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_ZIP_TRANSFORM_VIEW_H +#define _LIBCPP___RANGES_ZIP_TRANSFORM_VIEW_H + +#include <__config> + +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/invocable.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/empty_view.h> +#include <__ranges/movable_box.h> +#include <__ranges/view_interface.h> +#include <__ranges/zip_view.h> +#include <__type_traits/decay.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_referenceable.h> +#include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <tuple> // for std::apply + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template <move_constructible _Fn, input_range... _Views> + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable<invoke_result_t<_Fn&, range_reference_t<_Views>...>> +class zip_transform_view : public view_interface<zip_transform_view<_Fn, _Views...>> { + _LIBCPP_NO_UNIQUE_ADDRESS zip_view<_Views...> __zip_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Fn> __fun_; + + using _InnerView _LIBCPP_NODEBUG = zip_view<_Views...>; + template <bool _Const> + using __ziperator _LIBCPP_NODEBUG = iterator_t<__maybe_const<_Const, _InnerView>>; + template <bool _Const> + using __zentinel _LIBCPP_NODEBUG = sentinel_t<__maybe_const<_Const, _InnerView>>; + + template <bool> + class __iterator; + + template <bool> + class __sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI zip_transform_view() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit zip_transform_view(_Fn __fun, _Views... __views) + : __zip_(std::move(__views)...), __fun_(in_place, std::move(__fun)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { return __iterator<false>(*this, __zip_.begin()); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range<const _InnerView> && regular_invocable<const _Fn&, range_reference_t<const _Views>...> + { + return __iterator<true>(*this, __zip_.begin()); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() { + if constexpr (common_range<_InnerView>) { + return __iterator<false>(*this, __zip_.end()); + } else { + return __sentinel<false>(__zip_.end()); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range<const _InnerView> && regular_invocable<const _Fn&, range_reference_t<const _Views>...> + { + if constexpr (common_range<const _InnerView>) { + return __iterator<true>(*this, __zip_.end()); + } else { + return __sentinel<true>(__zip_.end()); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_InnerView> + { + return __zip_.size(); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range<const _InnerView> + { + return __zip_.size(); + } +}; + +template <class _Fn, class... _Ranges> +zip_transform_view(_Fn, _Ranges&&...) -> zip_transform_view<_Fn, views::all_t<_Ranges>...>; + +template <bool _Const, class _Fn, class... _Views> +struct __zip_transform_iterator_category_base {}; + +template <bool _Const, class _Fn, class... _Views> + requires forward_range<__maybe_const<_Const, zip_view<_Views...>>> +struct __zip_transform_iterator_category_base<_Const, _Fn, _Views...> { +private: + template <class _View> + using __tag _LIBCPP_NODEBUG = typename iterator_traits<iterator_t<__maybe_const<_Const, _View>>>::iterator_category; + + static consteval auto __get_iterator_category() { + if constexpr (!is_reference_v<invoke_result_t<__maybe_const<_Const, _Fn>&, + range_reference_t<__maybe_const<_Const, _Views>>...>>) { + return input_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, random_access_iterator_tag> && ...)) { + return random_access_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, bidirectional_iterator_tag> && ...)) { + return bidirectional_iterator_tag(); + } else if constexpr ((derived_from<__tag<_Views>, forward_iterator_tag> && ...)) { + return forward_iterator_tag(); + } else { + return input_iterator_tag(); + } + } + +public: + using iterator_category = decltype(__get_iterator_category()); +}; + +template <move_constructible _Fn, input_range... _Views> + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable<invoke_result_t<_Fn&, range_reference_t<_Views>...>> +template <bool _Const> +class zip_transform_view<_Fn, _Views...>::__iterator + : public __zip_transform_iterator_category_base<_Const, _Fn, _Views...> { + using _Parent _LIBCPP_NODEBUG = __maybe_const<_Const, zip_transform_view>; + using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _InnerView>; + + friend zip_transform_view<_Fn, _Views...>; + + _Parent* __parent_ = nullptr; + __ziperator<_Const> __inner_; + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, __ziperator<_Const> __inner) + : __parent_(std::addressof(__parent)), __inner_(std::move(__inner)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr auto __get_deref_and_invoke() const noexcept { + return [&__fun = *__parent_->__fun_](const auto&... __iters) noexcept(noexcept(std::invoke( + *__parent_->__fun_, *__iters...))) -> decltype(auto) { return std::invoke(__fun, *__iters...); }; + } + +public: + using iterator_concept = typename __ziperator<_Const>::iterator_concept; + using value_type = + remove_cvref_t<invoke_result_t<__maybe_const<_Const, _Fn>&, range_reference_t<__maybe_const<_Const, _Views>>...>>; + using difference_type = range_difference_t<_Base>; + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) + requires _Const && convertible_to<__ziperator<false>, __ziperator<_Const>> + : __parent_(__i.__parent_), __inner_(std::move(__i.__inner_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const + noexcept(noexcept(std::apply(__get_deref_and_invoke(), __zip_view_iterator_access::__get_underlying(__inner_)))) { + return std::apply(__get_deref_and_invoke(), __zip_view_iterator_access::__get_underlying(__inner_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__inner_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) + requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() + requires bidirectional_range<_Base> + { + --__inner_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) + requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __x) + requires random_access_range<_Base> + { + __inner_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __x) + requires random_access_range<_Base> + { + __inner_ -= __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const + requires random_access_range<_Base> + { + return std::apply( + [&]<class... _Is>(const _Is&... __iters) -> decltype(auto) { + return std::invoke(*__parent_->__fun_, __iters[iter_difference_t<_Is>(__n)]...); + }, + __zip_view_iterator_access::__get_underlying(__inner_)); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<__ziperator<_Const>> + { + return __x.__inner_ == __y.__inner_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires random_access_range<_Base> + { + return __x.__inner_ <=> __y.__inner_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + return __iterator(*__i.__parent_, __i.__inner_ - __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires sized_sentinel_for<__ziperator<_Const>, __ziperator<_Const>> + { + return __x.__inner_ - __y.__inner_; + } +}; + +template <move_constructible _Fn, input_range... _Views> + requires(view<_Views> && ...) && + (sizeof...(_Views) > 0) && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_Views>...> && + __referenceable<invoke_result_t<_Fn&, range_reference_t<_Views>...>> +template <bool _Const> +class zip_transform_view<_Fn, _Views...>::__sentinel { + __zentinel<_Const> __inner_; + + friend zip_transform_view<_Fn, _Views...>; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(__zentinel<_Const> __inner) : __inner_(__inner) {} + +public: + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __i) + requires _Const && convertible_to<__zentinel<false>, __zentinel<_Const>> + : __inner_(__i.__inner_) {} + + template <bool _OtherConst> + requires sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __x.__inner_ == __y.__inner_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _InnerView>> + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return __x.__inner_ - __y.__inner_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _InnerView>> + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { + return __x.__inner_ - __y.__inner_; + } +}; + +namespace views { +namespace __zip_transform { + +struct __fn { + template <class _Fn> + requires(move_constructible<decay_t<_Fn>> && regular_invocable<decay_t<_Fn>&> && + is_object_v<invoke_result_t<decay_t<_Fn>&>>) + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&&) const + noexcept(noexcept(auto(views::empty<decay_t<invoke_result_t<decay_t<_Fn>&>>>))) { + return views::empty<decay_t<invoke_result_t<decay_t<_Fn>&>>>; + } + + template <class _Fn, class... _Ranges> + requires(sizeof...(_Ranges) > 0) + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __fun, _Ranges&&... __rs) const + noexcept(noexcept(zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...))) + -> decltype(zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...)) { + return zip_transform_view(std::forward<_Fn>(__fun), std::forward<_Ranges>(__rs)...); + } +}; + +} // namespace __zip_transform +inline namespace __cpo { +inline constexpr auto zip_transform = __zip_transform::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ZIP_TRANSFORM_VIEW_H diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h index e2a194e..ce00c98 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -235,6 +235,13 @@ struct __zip_view_iterator_category_base<_Const, _Views...> { using iterator_category = input_iterator_tag; }; +struct __zip_view_iterator_access { + template <class _Iter> + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_underlying(_Iter& __iter) noexcept { + return (__iter.__current_); + } +}; + template <input_range... _Views> requires(view<_Views> && ...) && (sizeof...(_Views) > 0) template <bool _Const> @@ -255,6 +262,7 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base static constexpr bool __is_zip_view_iterator = true; friend struct __product_iterator_traits<__iterator>; + friend __zip_view_iterator_access; public: using iterator_concept = decltype(ranges::__get_zip_view_iterator_tag<_Const, _Views...>()); diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index 1b51571..a3b672b 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -155,8 +155,8 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { # ifndef _LIBCPP_CXX03_LANG template <class _TSp, class _Fp, class... _Args, size_t... _Indices> -inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) { - std::__invoke(std::move(std::get<1>(__t)), std::move(std::get<_Indices>(__t))...); +inline _LIBCPP_HIDE_FROM_ABI void __thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __index_sequence<_Indices...>) { + std::__invoke(std::move(std::get<_Indices + 1>(__t))...); } template <class _Fp> @@ -164,8 +164,7 @@ _LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) { // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); __thread_local_data().set_pointer(std::get<0>(*__p.get()).release()); - typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; - std::__thread_execute(*__p.get(), _Index()); + std::__thread_execute(*__p.get(), __make_index_sequence<tuple_size<_Fp>::value - 1>()); return nullptr; } diff --git a/libcxx/include/__tuple/make_tuple_types.h b/libcxx/include/__tuple/make_tuple_types.h index a5c9bcf..3c22ec8 100644 --- a/libcxx/include/__tuple/make_tuple_types.h +++ b/libcxx/include/__tuple/make_tuple_types.h @@ -14,12 +14,12 @@ #include <__fwd/array.h> #include <__fwd/tuple.h> #include <__tuple/tuple_element.h> -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_size.h> #include <__tuple/tuple_types.h> #include <__type_traits/copy_cvref.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> +#include <__utility/integer_sequence.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -38,38 +38,35 @@ template <class _TupleTypes, class _TupleIndices> struct __make_tuple_types_flat; template <template <class...> class _Tuple, class... _Types, size_t... _Idx> -struct __make_tuple_types_flat<_Tuple<_Types...>, __tuple_indices<_Idx...>> { +struct __make_tuple_types_flat<_Tuple<_Types...>, __index_sequence<_Idx...>> { // Specialization for pair, tuple, and __tuple_types template <class _Tp> using __apply_quals _LIBCPP_NODEBUG = __tuple_types<__copy_cvref_t<_Tp, __type_pack_element<_Idx, _Types...>>...>; }; template <class _Vt, size_t _Np, size_t... _Idx> -struct __make_tuple_types_flat<array<_Vt, _Np>, __tuple_indices<_Idx...>> { +struct __make_tuple_types_flat<array<_Vt, _Np>, __index_sequence<_Idx...>> { template <size_t> using __value_type _LIBCPP_NODEBUG = _Vt; template <class _Tp> using __apply_quals _LIBCPP_NODEBUG = __tuple_types<__copy_cvref_t<_Tp, __value_type<_Idx>>...>; }; -template <class _Tp, - size_t _Ep = tuple_size<__libcpp_remove_reference_t<_Tp> >::value, - size_t _Sp = 0, - bool _SameSize = (_Ep == tuple_size<__libcpp_remove_reference_t<_Tp> >::value)> +template <class _Tp> struct __make_tuple_types { - static_assert(_Sp <= _Ep, "__make_tuple_types input error"); using _RawTp _LIBCPP_NODEBUG = __remove_cvref_t<_Tp>; - using _Maker _LIBCPP_NODEBUG = __make_tuple_types_flat<_RawTp, typename __make_tuple_indices<_Ep, _Sp>::type>; - using type _LIBCPP_NODEBUG = typename _Maker::template __apply_quals<_Tp>; + using _Maker _LIBCPP_NODEBUG = + __make_tuple_types_flat<_RawTp, __make_index_sequence<tuple_size<__libcpp_remove_reference_t<_Tp>>::value>>; + using type _LIBCPP_NODEBUG = typename _Maker::template __apply_quals<_Tp>; }; -template <class... _Types, size_t _Ep> -struct __make_tuple_types<tuple<_Types...>, _Ep, 0, true> { +template <class... _Types> +struct __make_tuple_types<tuple<_Types...>> { using type _LIBCPP_NODEBUG = __tuple_types<_Types...>; }; -template <class... _Types, size_t _Ep> -struct __make_tuple_types<__tuple_types<_Types...>, _Ep, 0, true> { +template <class... _Types> +struct __make_tuple_types<__tuple_types<_Types...>> { using type _LIBCPP_NODEBUG = __tuple_types<_Types...>; }; diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h index f67c867..607ac3a 100644 --- a/libcxx/include/__tuple/tuple_element.h +++ b/libcxx/include/__tuple/tuple_element.h @@ -11,7 +11,6 @@ #include <__config> #include <__cstddef/size_t.h> -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_types.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__tuple/tuple_indices.h b/libcxx/include/__tuple/tuple_indices.h deleted file mode 100644 index 25dc9ec..0000000 --- a/libcxx/include/__tuple/tuple_indices.h +++ /dev/null @@ -1,37 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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___TUPLE_MAKE_TUPLE_INDICES_H -#define _LIBCPP___TUPLE_MAKE_TUPLE_INDICES_H - -#include <__config> -#include <__cstddef/size_t.h> -#include <__utility/integer_sequence.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#ifndef _LIBCPP_CXX03_LANG - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <size_t...> -struct __tuple_indices {}; - -template <size_t _Ep, size_t _Sp = 0> -struct __make_tuple_indices { - static_assert(_Sp <= _Ep, "__make_tuple_indices input error"); - typedef __make_indices_imp<_Ep, _Sp> type; -}; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP_CXX03_LANG - -#endif // _LIBCPP___TUPLE_MAKE_TUPLE_INDICES_H diff --git a/libcxx/include/__utility/integer_sequence.h b/libcxx/include/__utility/integer_sequence.h index d1c6e53..329826a 100644 --- a/libcxx/include/__utility/integer_sequence.h +++ b/libcxx/include/__utility/integer_sequence.h @@ -17,57 +17,41 @@ # pragma GCC system_header #endif +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_BEGIN_NAMESPACE_STD -template <size_t...> -struct __tuple_indices; +# if __has_builtin(__make_integer_seq) +template <template <class _Tp, _Tp...> class _BaseType, class _Tp, _Tp _SequenceSize> +using __make_integer_sequence_impl _LIBCPP_NODEBUG = __make_integer_seq<_BaseType, _Tp, _SequenceSize>; +# else +template <template <class _Tp, _Tp...> class _BaseType, class _Tp, _Tp _SequenceSize> +using __make_integer_sequence_impl _LIBCPP_NODEBUG = _BaseType<_Tp, __integer_pack(_SequenceSize)...>; +# endif -template <class _IdxType, _IdxType... _Values> +template <class _Tp, _Tp... _Indices> struct __integer_sequence { - template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType> - using __convert _LIBCPP_NODEBUG = _ToIndexSeq<_ToIndexType, _Values...>; - - template <size_t _Sp> - using __to_tuple_indices _LIBCPP_NODEBUG = __tuple_indices<(_Values + _Sp)...>; + using value_type = _Tp; + static_assert(is_integral<_Tp>::value, "std::integer_sequence can only be instantiated with an integral type"); + static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return sizeof...(_Indices); } }; -#if __has_builtin(__make_integer_seq) -template <size_t _Ep, size_t _Sp> -using __make_indices_imp _LIBCPP_NODEBUG = - typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template __to_tuple_indices<_Sp>; -#elif __has_builtin(__integer_pack) -template <size_t _Ep, size_t _Sp> -using __make_indices_imp _LIBCPP_NODEBUG = - typename __integer_sequence<size_t, __integer_pack(_Ep - _Sp)...>::template __to_tuple_indices<_Sp>; -#else -# error "No known way to get an integer pack from the compiler" -#endif +template <size_t... _Indices> +using __index_sequence _LIBCPP_NODEBUG = __integer_sequence<size_t, _Indices...>; -#if _LIBCPP_STD_VER >= 14 +template <size_t _SequenceSize> +using __make_index_sequence _LIBCPP_NODEBUG = __make_integer_sequence_impl<__integer_sequence, size_t, _SequenceSize>; -template <class _Tp, _Tp... _Ip> -struct integer_sequence { - typedef _Tp value_type; - static_assert(is_integral<_Tp>::value, "std::integer_sequence can only be instantiated with an integral type"); - static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return sizeof...(_Ip); } -}; +# if _LIBCPP_STD_VER >= 14 + +template <class _Tp, _Tp... _Indices> +struct integer_sequence : __integer_sequence<_Tp, _Indices...> {}; template <size_t... _Ip> using index_sequence = integer_sequence<size_t, _Ip...>; -# if __has_builtin(__make_integer_seq) - template <class _Tp, _Tp _Ep> -using make_integer_sequence _LIBCPP_NODEBUG = __make_integer_seq<integer_sequence, _Tp, _Ep>; - -# elif __has_builtin(__integer_pack) - -template <class _Tp, _Tp _SequenceSize> -using make_integer_sequence _LIBCPP_NODEBUG = integer_sequence<_Tp, __integer_pack(_SequenceSize)...>; - -# else -# error "No known way to get an integer pack from the compiler" -# endif +using make_integer_sequence _LIBCPP_NODEBUG = __make_integer_sequence_impl<integer_sequence, _Tp, _Ep>; template <size_t _Np> using make_index_sequence = make_integer_sequence<size_t, _Np>; @@ -75,16 +59,18 @@ using make_index_sequence = make_integer_sequence<size_t, _Np>; template <class... _Tp> using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; -# if _LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 20 // Executes __func for every element in an index_sequence. template <size_t... _Index, class _Function> _LIBCPP_HIDE_FROM_ABI constexpr void __for_each_index_sequence(index_sequence<_Index...>, _Function __func) { (__func.template operator()<_Index>(), ...); } -# endif // _LIBCPP_STD_VER >= 20 +# endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_STD_VER >= 14 +# endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD +#endif // _LIBCPP_CXX03_LANG + #endif // _LIBCPP___UTILITY_INTEGER_SEQUENCE_H diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index dbacbce..33694c52 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -18,7 +18,6 @@ #include <__fwd/array.h> #include <__fwd/pair.h> #include <__fwd/tuple.h> -#include <__tuple/tuple_indices.h> #include <__tuple/tuple_like_no_subrange.h> #include <__tuple/tuple_size.h> #include <__type_traits/common_reference.h> @@ -40,6 +39,7 @@ #include <__type_traits/unwrap_ref.h> #include <__utility/declval.h> #include <__utility/forward.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> @@ -225,8 +225,8 @@ struct pair : pair(__pc, __first_args, __second_args, - typename __make_tuple_indices<sizeof...(_Args1)>::type(), - typename __make_tuple_indices<sizeof...(_Args2) >::type()) {} + __make_index_sequence<sizeof...(_Args1)>(), + __make_index_sequence<sizeof...(_Args2)>()) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(__conditional_t<is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value, @@ -440,8 +440,8 @@ private: pair(piecewise_construct_t, tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, - __tuple_indices<_I1...>, - __tuple_indices<_I2...>) + __index_sequence<_I1...>, + __index_sequence<_I2...>) : first(std::forward<_Args1>(std::get<_I1>(__first_args))...), second(std::forward<_Args2>(std::get<_I2>(__second_args))...) {} #endif diff --git a/libcxx/include/bitset b/libcxx/include/bitset index d109f27..e2b4615 100644 --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -147,7 +147,6 @@ template <size_t N> struct hash<std::bitset<N>>; # include <__functional/hash.h> # include <__functional/identity.h> # include <__functional/unary_function.h> -# include <__tuple/tuple_indices.h> # include <__type_traits/enable_if.h> # include <__type_traits/integral_constant.h> # include <__type_traits/is_char_like_type.h> @@ -314,7 +313,7 @@ private: _LIBCPP_HIDE_FROM_ABI void __init(unsigned long long __v, true_type) _NOEXCEPT; # else template <size_t... _Indices> - _LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, std::__tuple_indices<_Indices...>) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI constexpr __bitset(unsigned long long __v, __index_sequence<_Indices...>) _NOEXCEPT : __first_{static_cast<__storage_type>(__v >> (_Indices * __bits_per_word))...} {} # endif // _LIBCPP_CXX03_LANG }; @@ -352,10 +351,9 @@ template <size_t _N_words, size_t _Size> inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT # ifndef _LIBCPP_CXX03_LANG : __bitset(__v, - std::__make_indices_imp< (_N_words < (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1) - ? _N_words - : (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1, - 0>{}) + __make_index_sequence<(_N_words < (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1) + ? _N_words + : (sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1>()) # endif { # ifdef _LIBCPP_CXX03_LANG diff --git a/libcxx/include/future b/libcxx/include/future index abdd82d..3df9dc9 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -1842,15 +1842,12 @@ public: _LIBCPP_HIDE_FROM_ABI __async_func(__async_func&& __f) : __f_(std::move(__f.__f_)) {} - _LIBCPP_HIDE_FROM_ABI _Rp operator()() { - typedef typename __make_tuple_indices<1 + sizeof...(_Args), 1>::type _Index; - return __execute(_Index()); - } + _LIBCPP_HIDE_FROM_ABI _Rp operator()() { return __execute(__make_index_sequence<sizeof...(_Args) + 1>()); } private: template <size_t... _Indices> - _LIBCPP_HIDE_FROM_ABI _Rp __execute(__tuple_indices<_Indices...>) { - return std::__invoke(std::move(std::get<0>(__f_)), std::move(std::get<_Indices>(__f_))...); + _LIBCPP_HIDE_FROM_ABI _Rp __execute(__index_sequence<_Indices...>) { + return std::__invoke(std::move(std::get<_Indices>(__f_))...); } }; diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 78607f2..ac49720 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1943,6 +1943,9 @@ module std [system] { header "__ranges/zip_view.h" export std.utility.pair } + module zip_transform_view { + header "__ranges/zip_transform_view.h" + } header "ranges" export * @@ -2110,7 +2113,6 @@ module std [system] { module make_tuple_types { header "__tuple/make_tuple_types.h" } module sfinae_helpers { header "__tuple/sfinae_helpers.h" } module tuple_element { header "__tuple/tuple_element.h" } - module tuple_indices { header "__tuple/tuple_indices.h" } module tuple_like_ext { header "__tuple/tuple_like_ext.h" } module tuple_like_no_subrange { header "__tuple/tuple_like_no_subrange.h" } module tuple_like { header "__tuple/tuple_like.h" } diff --git a/libcxx/include/mutex b/libcxx/include/mutex index dc8e711..78d8c8a 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -469,17 +469,14 @@ public: [[nodiscard]] _LIBCPP_HIDE_FROM_ABI scoped_lock(adopt_lock_t, _MArgs&... __margs) : __t_(__margs...) {} - _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { - typedef typename __make_tuple_indices<sizeof...(_MArgs)>::type _Indices; - __unlock_unpack(_Indices{}, __t_); - } + _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { __unlock_unpack(make_index_sequence<sizeof...(_MArgs)>(), __t_); } scoped_lock(scoped_lock const&) = delete; scoped_lock& operator=(scoped_lock const&) = delete; private: template <size_t... _Indx> - _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { + _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(index_sequence<_Indx...>, _MutexTuple& __mt) { (std::get<_Indx>(__mt).unlock(), ...); } diff --git a/libcxx/include/ranges b/libcxx/include/ranges index 2a6321b..96d7a6b 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -339,6 +339,16 @@ namespace std::ranges { namespace views { inline constexpr unspecified zip = unspecified; } // C++23 + // [range.zip.transform], zip transform view + template<move_constructible F, input_range... Views> + requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> && + regular_invocable<F&, range_reference_t<Views>...> && + can-reference<invoke_result_t<F&, range_reference_t<Views>...>> + class zip_transform_view; // C++23 + + namespace views { inline constexpr unspecified zip_transform = unspecified; } // C++23 + + // [range.as.rvalue] template <view V> requires input_range<V> @@ -439,6 +449,7 @@ namespace std { # include <__ranges/join_with_view.h> # include <__ranges/repeat_view.h> # include <__ranges/to.h> +# include <__ranges/zip_transform_view.h> # include <__ranges/zip_view.h> # endif diff --git a/libcxx/include/regex b/libcxx/include/regex index bbc21e2..9bbc3a6 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -2120,7 +2120,7 @@ public: __ranges_.push_back( std::make_pair(__traits_.transform(__b.begin(), __b.end()), __traits_.transform(__e.begin(), __e.end()))); } else { - if (__b.size() != 1 || __e.size() != 1) + if (__b.size() != 1 || __e.size() != 1 || char_traits<typename string_type::value_type>::lt(__e[0], __b[0])) std::__throw_regex_error<regex_constants::error_range>(); if (__icase_) { __b[0] = __traits_.translate_nocase(__b[0]); diff --git a/libcxx/include/scoped_allocator b/libcxx/include/scoped_allocator index 7b8a9c9..74effc5 100644 --- a/libcxx/include/scoped_allocator +++ b/libcxx/include/scoped_allocator @@ -434,10 +434,10 @@ public: piecewise_construct, __transform_tuple(typename __uses_alloc_ctor< _T1, inner_allocator_type&, _Args1... >::type(), std::move(__x), - typename __make_tuple_indices<sizeof...(_Args1)>::type{}), + __make_index_sequence<sizeof...(_Args1)>()), __transform_tuple(typename __uses_alloc_ctor< _T2, inner_allocator_type&, _Args2... >::type(), std::move(__y), - typename __make_tuple_indices<sizeof...(_Args2)>::type{})); + __make_index_sequence<sizeof...(_Args2)>())); } template <class _T1, class _T2> @@ -503,20 +503,20 @@ private: template <class... _Args, size_t... _Idx> _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...> - __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { + __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __index_sequence<_Idx...>) { return std::forward_as_tuple(std::get<_Idx>(std::move(__t))...); } template <class... _Args, size_t... _Idx> _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t, inner_allocator_type&, _Args&&...> - __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { + __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __index_sequence<_Idx...>) { using _Tup = tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>; return _Tup(allocator_arg, inner_allocator(), std::get<_Idx>(std::move(__t))...); } template <class... _Args, size_t... _Idx> _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., inner_allocator_type&> - __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) { + __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __index_sequence<_Idx...>) { using _Tup = tuple<_Args&&..., inner_allocator_type&>; return _Tup(std::get<_Idx>(std::move(__t))..., inner_allocator()); } diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 75021f0..662d926 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -229,7 +229,6 @@ template <class... Types> # include <__tuple/make_tuple_types.h> # include <__tuple/sfinae_helpers.h> # include <__tuple/tuple_element.h> -# include <__tuple/tuple_indices.h> # include <__tuple/tuple_like_ext.h> # include <__tuple/tuple_size.h> # include <__tuple/tuple_types.h> @@ -457,15 +456,15 @@ struct __tuple_impl; template <size_t... _Indx, class... _Tp> struct _LIBCPP_DECLSPEC_EMPTY_BASES - __tuple_impl<__tuple_indices<_Indx...>, _Tp...> : public __tuple_leaf<_Indx, _Tp>... { + __tuple_impl<__index_sequence<_Indx...>, _Tp...> : public __tuple_leaf<_Indx, _Tp>... { _LIBCPP_HIDE_FROM_ABI constexpr __tuple_impl() noexcept( __all<is_nothrow_default_constructible<_Tp>::value...>::value) {} template <size_t... _Uf, class... _Tf, size_t... _Ul, class... _Tl, class... _Up> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl( - __tuple_indices<_Uf...>, + __index_sequence<_Uf...>, __tuple_types<_Tf...>, - __tuple_indices<_Ul...>, + __index_sequence<_Ul...>, __tuple_types<_Tl...>, _Up&&... __u) noexcept(__all<is_nothrow_constructible<_Tf, _Up>::value...>::value && __all<is_nothrow_default_constructible<_Tl>::value...>::value) @@ -475,9 +474,9 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_impl( allocator_arg_t, const _Alloc& __a, - __tuple_indices<_Uf...>, + __index_sequence<_Uf...>, __tuple_types<_Tf...>, - __tuple_indices<_Ul...>, + __index_sequence<_Ul...>, __tuple_types<_Tl...>, _Up&&... __u) : __tuple_leaf<_Uf, _Tf>(__uses_alloc_ctor<_Tf, _Alloc, _Up>(), __a, std::forward<_Up>(__u))..., @@ -518,19 +517,19 @@ struct _LIBCPP_DECLSPEC_EMPTY_BASES template <class _Dest, class _Source, size_t... _Np> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void -__memberwise_copy_assign(_Dest& __dest, _Source const& __source, __tuple_indices<_Np...>) { +__memberwise_copy_assign(_Dest& __dest, _Source const& __source, __index_sequence<_Np...>) { std::__swallow(((std::get<_Np>(__dest) = std::get<_Np>(__source)), void(), 0)...); } template <class _Dest, class _Source, class... _Up, size_t... _Np> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void -__memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up...>, __tuple_indices<_Np...>) { +__memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up...>, __index_sequence<_Np...>) { std::__swallow(((std::get<_Np>(__dest) = std::forward<_Up>(std::get<_Np>(__source))), void(), 0)...); } template <class... _Tp> class _LIBCPP_NO_SPECIALIZATIONS tuple { - typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> _BaseT; + typedef __tuple_impl<__make_index_sequence<sizeof...(_Tp)>, _Tp...> _BaseT; _BaseT __base_; @@ -568,9 +567,9 @@ public: tuple(allocator_arg_t, _Alloc const& __a) : __base_(allocator_arg_t(), __a, - __tuple_indices<>(), + __index_sequence<>(), __tuple_types<>(), - typename __make_tuple_indices<sizeof...(_Tp), 0>::type(), + __make_index_sequence<sizeof...(_Tp)>(), __tuple_types<_Tp...>()) {} // tuple(const T&...) constructors (including allocator_arg_t variants) @@ -579,10 +578,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> >::value) tuple(const _Tp&... __t) noexcept(_And<is_nothrow_copy_constructible<_Tp>...>::value) - : __base_(typename __make_tuple_indices<sizeof...(_Tp)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), - typename __make_tuple_indices<0>::type(), - typename __make_tuple_types<tuple, 0>::type(), + : __base_(__make_index_sequence<sizeof...(_Tp)>(), + __tuple_types<_Tp...>(), + __index_sequence<>(), + __tuple_types<>(), __t...) {} template <class _Alloc, @@ -593,10 +592,10 @@ public: tuple(allocator_arg_t, const _Alloc& __a, const _Tp&... __t) : __base_(allocator_arg_t(), __a, - typename __make_tuple_indices<sizeof...(_Tp)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Tp)>::type(), - typename __make_tuple_indices<0>::type(), - typename __make_tuple_types<tuple, 0>::type(), + __make_index_sequence<sizeof...(_Tp)>(), + __tuple_types<_Tp...>(), + __index_sequence<>(), + __tuple_types<>(), __t...) {} // tuple(U&& ...) constructors (including allocator_arg_t variants) @@ -616,10 +615,10 @@ public: int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value) tuple(_Up&&... __u) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value) - : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), - typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), + : __base_(__make_index_sequence<sizeof...(_Up)>(), + __tuple_types<_Tp...>(), + __index_sequence<>(), + __tuple_types<>(), std::forward<_Up>(__u)...) {} template <class _Alloc, @@ -630,10 +629,10 @@ public: tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u) : __base_(allocator_arg_t(), __a, - typename __make_tuple_indices<sizeof...(_Up)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Up)>::type(), - typename __make_tuple_indices<sizeof...(_Tp), sizeof...(_Up)>::type(), - typename __make_tuple_types<tuple, sizeof...(_Tp), sizeof...(_Up)>::type(), + __make_index_sequence<sizeof...(_Up)>(), + __tuple_types<_Tp...>(), + __index_sequence<>(), + __tuple_types<>(), std::forward<_Up>(__u)...) {} // Copy and move constructors (including the allocator_arg_t variants) @@ -838,7 +837,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(_If<_And<is_copy_assignable<_Tp>...>::value, tuple, __nat> const& __tuple) noexcept( _And<is_nothrow_copy_assignable<_Tp>...>::value) { - std::__memberwise_copy_assign(*this, __tuple, typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_copy_assign(*this, __tuple, __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -846,7 +845,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr const tuple& operator=(tuple const& __tuple) const requires(_And<is_copy_assignable<const _Tp>...>::value) { - std::__memberwise_copy_assign(*this, __tuple, typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_copy_assign(*this, __tuple, __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -854,7 +853,7 @@ public: requires(_And<is_assignable<const _Tp&, _Tp>...>::value) { std::__memberwise_forward_assign( - *this, std::move(__tuple), __tuple_types<_Tp...>(), typename __make_tuple_indices<sizeof...(_Tp)>::type()); + *this, std::move(__tuple), __tuple_types<_Tp...>(), __make_index_sequence<sizeof...(_Tp)>()); return *this; } # endif // _LIBCPP_STD_VER >= 23 @@ -863,7 +862,7 @@ public: operator=(_If<_And<is_move_assignable<_Tp>...>::value, tuple, __nat>&& __tuple) noexcept( _And<is_nothrow_move_assignable<_Tp>...>::value) { std::__memberwise_forward_assign( - *this, std::move(__tuple), __tuple_types<_Tp...>(), typename __make_tuple_indices<sizeof...(_Tp)>::type()); + *this, std::move(__tuple), __tuple_types<_Tp...>(), __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -873,7 +872,7 @@ public: int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(tuple<_Up...> const& __tuple) noexcept(_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value) { - std::__memberwise_copy_assign(*this, __tuple, typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_copy_assign(*this, __tuple, __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -883,7 +882,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(tuple<_Up...>&& __tuple) noexcept(_And<is_nothrow_assignable<_Tp&, _Up>...>::value) { std::__memberwise_forward_assign( - *this, std::move(__tuple), __tuple_types<_Up...>(), typename __make_tuple_indices<sizeof...(_Tp)>::type()); + *this, std::move(__tuple), __tuple_types<_Up...>(), __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -892,7 +891,7 @@ public: enable_if_t< _And<_BoolConstant<sizeof...(_Tp) == sizeof...(_UTypes)>, is_assignable<const _Tp&, const _UTypes&>...>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr const tuple& operator=(const tuple<_UTypes...>& __u) const { - std::__memberwise_copy_assign(*this, __u, typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_copy_assign(*this, __u, __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -900,8 +899,7 @@ public: enable_if_t< _And<_BoolConstant<sizeof...(_Tp) == sizeof...(_UTypes)>, is_assignable<const _Tp&, _UTypes>...>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr const tuple& operator=(tuple<_UTypes...>&& __u) const { - std::__memberwise_forward_assign( - *this, __u, __tuple_types<_UTypes...>(), typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_forward_assign(*this, __u, __tuple_types<_UTypes...>(), __make_index_sequence<sizeof...(_Tp)>()); return *this; } # endif // _LIBCPP_STD_VER >= 23 @@ -967,7 +965,7 @@ public: __enable_if_t< _And< _BoolConstant<_Np == sizeof...(_Tp)>, is_assignable<_Tp&, _Up const&>... >::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(array<_Up, _Np> const& __array) noexcept(_And<is_nothrow_assignable<_Tp&, _Up const&>...>::value) { - std::__memberwise_copy_assign(*this, __array, typename __make_tuple_indices<sizeof...(_Tp)>::type()); + std::__memberwise_copy_assign(*this, __array, __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -979,10 +977,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(array<_Up, _Np>&& __array) noexcept(_And<is_nothrow_assignable<_Tp&, _Up>...>::value) { std::__memberwise_forward_assign( - *this, - std::move(__array), - __tuple_types<_If<true, _Up, _Tp>...>(), - typename __make_tuple_indices<sizeof...(_Tp)>::type()); + *this, std::move(__array), __tuple_types<_If<true, _Up, _Tp>...>(), __make_index_sequence<sizeof...(_Tp)>()); return *this; } @@ -1291,17 +1286,17 @@ template <class _Rp, class _Indices, class _Tuple0, class... _Tuples> struct __tuple_cat_return_ref_imp; template <class... _Types, size_t... _I0, class _Tuple0> -struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0> { +struct __tuple_cat_return_ref_imp<tuple<_Types...>, __index_sequence<_I0...>, _Tuple0> { using _T0 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple0>; typedef tuple<_Types..., __copy_cvref_t<_Tuple0, typename tuple_element<_I0, _T0>::type>&&...> type; }; template <class... _Types, size_t... _I0, class _Tuple0, class _Tuple1, class... _Tuples> -struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0, _Tuple1, _Tuples...> +struct __tuple_cat_return_ref_imp<tuple<_Types...>, __index_sequence<_I0...>, _Tuple0, _Tuple1, _Tuples...> : public __tuple_cat_return_ref_imp< tuple<_Types..., __copy_cvref_t<_Tuple0, typename tuple_element<_I0, __libcpp_remove_reference_t<_Tuple0>>::type>&&...>, - typename __make_tuple_indices<tuple_size<__libcpp_remove_reference_t<_Tuple1> >::value>::type, + __make_index_sequence<tuple_size<__libcpp_remove_reference_t<_Tuple1> >::value>, _Tuple1, _Tuples...> {}; @@ -1309,7 +1304,7 @@ template <class _Tuple0, class... _Tuples> struct __tuple_cat_return_ref : public __tuple_cat_return_ref_imp< tuple<>, - typename __make_tuple_indices< tuple_size<__libcpp_remove_reference_t<_Tuple0> >::value >::type, + __make_index_sequence< tuple_size<__libcpp_remove_reference_t<_Tuple0> >::value >, _Tuple0, _Tuples...> {}; @@ -1317,7 +1312,7 @@ template <class _Types, class _I0, class _J0> struct __tuple_cat; template <class... _Types, size_t... _I0, size_t... _J0> -struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J0...> > { +struct __tuple_cat<tuple<_Types...>, __index_sequence<_I0...>, __index_sequence<_J0...>> { template <class _Tuple0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __tuple_cat_return_ref<tuple<_Types...>&&, _Tuple0&&>::type @@ -1335,8 +1330,8 @@ struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J using _T0 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple0>; using _T1 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple1>; return __tuple_cat<tuple<_Types..., __copy_cvref_t<_Tuple0, typename tuple_element<_J0, _T0>::type>&&...>, - typename __make_tuple_indices<sizeof...(_Types) + tuple_size<_T0>::value>::type, - typename __make_tuple_indices<tuple_size<_T1>::value>::type>()( + __make_index_sequence<sizeof...(_Types) + tuple_size<_T0>::value>, + __make_index_sequence<tuple_size<_T1>::value>>()( std::forward_as_tuple( std::forward<_Types>(std::get<_I0>(__t))..., std::get<_J0>(std::forward<_Tuple0>(__t0))...), std::forward<_Tuple1>(__t1), @@ -1346,7 +1341,7 @@ struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J template <class _TupleDst, class _TupleSrc, size_t... _Indices> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _TupleDst -__tuple_cat_select_element_wise(_TupleSrc&& __src, __tuple_indices<_Indices...>) { +__tuple_cat_select_element_wise(_TupleSrc&& __src, __index_sequence<_Indices...>) { static_assert(tuple_size<_TupleDst>::value == tuple_size<_TupleSrc>::value, "misuse of __tuple_cat_select_element_wise with tuples of different sizes"); return _TupleDst(std::get<_Indices>(std::forward<_TupleSrc>(__src))...); @@ -1357,10 +1352,10 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __tuple_cat_ tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls) { using _T0 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple0>; using _TRet _LIBCPP_NODEBUG = typename __tuple_cat_return<_Tuple0, _Tuples...>::type; - using _T0Indices _LIBCPP_NODEBUG = typename __make_tuple_indices<tuple_size<_T0>::value>::type; - using _TRetIndices _LIBCPP_NODEBUG = typename __make_tuple_indices<tuple_size<_TRet>::value>::type; + using _T0Indices _LIBCPP_NODEBUG = __make_index_sequence<tuple_size<_T0>::value>; + using _TRetIndices _LIBCPP_NODEBUG = __make_index_sequence<tuple_size<_TRet>::value>; return std::__tuple_cat_select_element_wise<_TRet>( - __tuple_cat<tuple<>, __tuple_indices<>, _T0Indices>()( + __tuple_cat<tuple<>, __index_sequence<>, _T0Indices>()( tuple<>(), std::forward<_Tuple0>(__t0), std::forward<_Tuples>(__tpls)...), _TRetIndices()); } @@ -1376,7 +1371,7 @@ struct uses_allocator<tuple<_Tp...>, _Alloc> : true_type {}; // clang-format off template <class _Fn, class _Tuple, size_t... _Id> inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) -__apply_tuple_impl(_Fn&& __f, _Tuple&& __t, __tuple_indices<_Id...>) +__apply_tuple_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Id...>) _LIBCPP_NOEXCEPT_RETURN(std::__invoke(std::forward<_Fn>(__f), std::get<_Id>(std::forward<_Tuple>(__t))...)) template <class _Fn, class _Tuple> @@ -1384,28 +1379,28 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& _LIBCPP_NOEXCEPT_RETURN(std::__apply_tuple_impl( std::forward<_Fn>(__f), std::forward<_Tuple>(__t), - typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) + make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>())) #if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, size_t... _Idx> -inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } #else template <class _Tp, class _Tuple, size_t... _Idx> -inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>, +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>, enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr) _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) #endif // _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, - class _Seq = typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type, class = void> + class _Seq = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>, class = void> inline constexpr bool __can_make_from_tuple = false; template <class _Tp, class _Tuple, size_t... _Idx> -inline constexpr bool __can_make_from_tuple<_Tp, _Tuple, __tuple_indices<_Idx...>, +inline constexpr bool __can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>, enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::declval<_Tuple>()))...>>> = true; // Based on LWG3528(https://wg21.link/LWG3528) and http://eel.is/c++draft/description#structure.requirements-9, @@ -1420,7 +1415,7 @@ template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp #endif // _LIBCPP_STD_VER >= 20 inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t) _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>( - std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) + std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>())) # undef _LIBCPP_NOEXCEPT_RETURN # endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/variant b/libcxx/include/variant index ede9f48..9beef14 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -1127,14 +1127,14 @@ template <class _IdxSeq> struct __make_overloads_imp; template <size_t... _Idx> -struct __make_overloads_imp<__tuple_indices<_Idx...> > { +struct __make_overloads_imp<index_sequence<_Idx...> > { template <class... _Types> using _Apply _LIBCPP_NODEBUG = __all_overloads<__overload<_Types, _Idx>...>; }; template <class... _Types> using _MakeOverloads _LIBCPP_NODEBUG = - typename __make_overloads_imp< __make_indices_imp<sizeof...(_Types), 0> >::template _Apply<_Types...>; + typename __make_overloads_imp<make_index_sequence<sizeof...(_Types)>>::template _Apply<_Types...>; template <class _Tp, class... _Types> using __best_match_t _LIBCPP_NODEBUG = typename invoke_result_t<_MakeOverloads<_Types...>, _Tp, _Tp>::type; diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc index adabeeb..7ede42e 100644 --- a/libcxx/modules/std/ranges.inc +++ b/libcxx/modules/std/ranges.inc @@ -289,16 +289,16 @@ export namespace std { namespace views { using std::ranges::views::zip; } // namespace views -#endif // _LIBCPP_STD_VER >= 23 -#if 0 // [range.zip.transform], zip transform view using std::ranges::zip_transform_view; namespace views { using std::ranges::views::zip_transform; } +#endif // _LIBCPP_STD_VER >= 23 +#if 0 using std::ranges::adjacent_view; namespace views { diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.zip.transform/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.zip.transform/no_unique_address.compile.pass.cpp new file mode 100644 index 0000000..4b66862 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.zip.transform/no_unique_address.compile.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, c++20 +// XFAIL: msvc + +// This test ensures that we use `[[no_unique_address]]` in `zip_transform_view`. + +#include <ranges> + +struct View : std::ranges::view_base { + int* begin() const; + int* end() const; +}; + +struct Pred { + template <class... Args> + bool operator()(const Args&...) const; +}; + +template <class View> +struct Test { + [[no_unique_address]] View view; + char c; +}; + +static_assert(sizeof(std::ranges::zip_transform_view<Pred, View>) == 1); diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp index 6137409..25cc08a 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -// Clang-18 fixed some spurious clang diagnostics. Once clang-18 is the -// minimum required version these obsolete tests can be removed. -// TODO(LLVM-20) remove spurious clang diagnostic tests. - // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // With clang-cl, some warnings have a 'which is a Microsoft extension' suffix @@ -59,12 +55,12 @@ void test() { { std::expected<int, int> e; e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}} // expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}} e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}} // expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}} } @@ -73,27 +69,27 @@ void test() { { const std::expected<int, int> e; e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} } // Test && overload { std::expected<int, int> e; std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} } // Test const&& overload { const std::expected<int, int> e; std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-2 {{no matching constructor for initialization of{{.*}}}} } } // clang-format on diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp index 16233cd..2dd3acd 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -// Clang-18 fixed some spurious clang diagnostics. Once clang-18 is the -// minumum required version these obsolete tests can be removed. -// TODO(LLVM-20) remove spurious clang diagnostic tests. - // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // With clang-cl, some warnings have a 'which is a Microsoft extension' suffix @@ -60,13 +56,13 @@ void test() { { std::expected<void, int> e; e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}} // expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}} // expected-error-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}}} e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}} // expected-warning-re@*:* 0-1 {{union member {{.*}} has reference type {{.*}}, which is a Microsoft extension}} } @@ -75,9 +71,9 @@ void test() { { const std::expected<void, int> e; e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} // expected-error-re@*:* 0-1 {{call to deleted constructor of {{.*}}}} } @@ -85,18 +81,18 @@ void test() { { std::expected<void, int> e; std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} } // Test const&& overload { const std::expected<void, int> e; std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}} - // expected-error-re@*:* 0-1 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}} + // expected-error-re@*:* 0-1 {{no matching constructor for initialization of{{.*}}}} } } // clang-format on diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp index b162c2d..1b42695 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // XFAIL: !has-64-bit-atomics -// Older versions of clang have a bug with atomic builtins affecting double and long double. -// Fixed by 5fdd0948. -// XFAIL: target=powerpc-ibm-{{.*}} && clang-18 - // https://github.com/llvm/llvm-project/issues/72893 // XFAIL: target={{x86_64-.*}} && tsan diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp index 8784037..cac7352 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // XFAIL: !has-64-bit-atomics -// Older versions of clang have a bug with atomic builtins affecting double and long double. -// Fixed by 5fdd0948. -// XFAIL: target=powerpc-ibm-{{.*}} && clang-18 - // https://github.com/llvm/llvm-project/issues/72893 // XFAIL: target={{x86_64-.*}} && tsan diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp index e0e0794..d38a2d2 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // XFAIL: !has-64-bit-atomics -// Older versions of clang have a bug with atomic builtins affecting double and long double. -// Fixed by 5fdd0948. -// XFAIL: target=powerpc-ibm-{{.*}} && clang-18 - // floating-point-type operator-=(floating-point-type) volatile noexcept; // floating-point-type operator-=(floating-point-type) noexcept; diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp index 7e2c101..c53b032 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // XFAIL: !has-64-bit-atomics -// Older versions of clang have a bug with atomic builtins affecting double and long double. -// Fixed by 5fdd0948. -// XFAIL: target=powerpc-ibm-{{.*}} && clang-18 - // floating-point-type operator+=(floating-point-type) volatile noexcept; // floating-point-type operator+=(floating-point-type) noexcept; diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp index 6929831..172c97f 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_copy.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14 -// Older versions of clang may encounter a backend error (see 0295c2ad): -// Pass-by-value arguments with alignment greater than register width are not supported. -// XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18 - // <experimental/simd> // // [simd.class] diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp index a496938..056d6f6 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp @@ -8,10 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14 -// Older versions of clang may encounter a backend error (see 0295c2ad): -// Pass-by-value arguments with alignment greater than register width are not supported. -// XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && clang-18 - // FIXME: The following issue occurs on Windows to Armv7 Ubuntu Linux: // Assertion failed: N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type" // XFAIL: target=armv7-unknown-linux-gnueabihf diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp index 4cd8fad..7bcc584 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp @@ -11,7 +11,6 @@ // UNSUPPORTED: c++03, c++11 // These compiler versions and platforms don't enable sized deallocation by default. -// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(apple-clang-17): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation @@ -20,10 +19,6 @@ // ADDITIONAL_COMPILE_FLAGS(target=armv7-w64-windows-gnu): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=arm64ec-w64-windows-gnu): -fsized-deallocation -// Android clang-r536225 identifies as clang-19.0 but it predates the real -// LLVM 19.0.0, so it also leaves sized deallocation off by default. -// UNSUPPORTED: android && clang-19.0 - // UNSUPPORTED: sanitizer-new-delete // Sized deallocation was introduced in LLVM 11 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp index 7b96b01..e6e8532 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp @@ -11,7 +11,6 @@ // UNSUPPORTED: c++03, c++11 // These compiler versions and platforms don't enable sized deallocation by default. -// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(apple-clang-17): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation @@ -20,10 +19,6 @@ // ADDITIONAL_COMPILE_FLAGS(target=armv7-w64-windows-gnu): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=arm64ec-w64-windows-gnu): -fsized-deallocation -// Android clang-r536225 identifies as clang-19.0 but it predates the real -// LLVM 19.0.0, so it also leaves sized deallocation off by default. -// UNSUPPORTED: android && clang-19.0 - // UNSUPPORTED: sanitizer-new-delete // Sized deallocation was introduced in LLVM 11 diff --git a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp index 3f4317a..4e24dbe 100644 --- a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp +++ b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp @@ -18,6 +18,8 @@ #include <type_traits> #include <utility> +#include "test_macros.h" + // Test for basic properties of C++20 16.3.3.3.6 [customization.point.object]. template <class CPO, class... Args> constexpr bool test(CPO& o, Args&&...) { @@ -26,7 +28,7 @@ constexpr bool test(CPO& o, Args&&...) { static_assert(std::is_trivially_copyable_v<CPO>); static_assert(std::is_trivially_default_constructible_v<CPO>); - auto p = o; + auto p = o; using T = decltype(p); // The type of a customization point object, ignoring cv-qualifiers, shall model semiregular. @@ -89,11 +91,15 @@ static_assert(test(std::views::counted, a, 10)); static_assert(test(std::views::drop, a, 10)); //static_assert(test(std::views::drop_while, a, [](int x){ return x < 10; })); //static_assert(test(std::views::elements<0>, pairs)); -static_assert(test(std::views::filter, a, [](int x){ return x < 10; })); +static_assert(test(std::views::filter, a, [](int x) { return x < 10; })); static_assert(test(std::views::join, arrays)); //static_assert(test(std::views::split, a, 4)); static_assert(test(std::views::lazy_split, a, 4)); static_assert(test(std::views::reverse, a)); static_assert(test(std::views::take, a, 10)); //static_assert(test(std::views::take_while, a, [](int x){ return x < 10; })); -static_assert(test(std::views::transform, a, [](int x){ return x + 1; })); +static_assert(test(std::views::transform, a, [](int x) { return x + 1; })); + +#if TEST_STD_VER >= 23 +static_assert(test(std::views::zip_transform, [](int x, int y) { return x + y; }, a, a)); +#endif diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp index 2ab4c11b..44ce325 100644 --- a/libcxx/test/std/numerics/c.math/signbit.pass.cpp +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -12,7 +12,7 @@ // UNSUPPORTED: windows // These compilers don't support constexpr `__builtin_signbit` yet. -// UNSUPPORTED: clang-18, clang-19, apple-clang-16, apple-clang-17 +// UNSUPPORTED: clang-19, apple-clang-16, apple-clang-17 // GCC warns about signbit comparing `bool_v < 0`, which we're testing // ADDITIONAL_COMPILE_FLAGS(gcc): -Wno-bool-compare diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/begin.pass.cpp new file mode 100644 index 0000000..9b326e1 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/begin.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// 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 begin(); +// constexpr auto begin() const +// requires range<const InnerView> && +// regular_invocable<const F&, range_reference_t<const Views>...>; + +#include <ranges> + +#include <cassert> +#include <concepts> + +#include "types.h" + +template <class T> +concept HasConstBegin = requires(const T& ct) { ct.begin(); }; + +template <class T> +concept HasBegin = requires(T& t) { t.begin(); }; + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + { + // all underlying iterators should be at the begin position + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::views::iota(0), std::ranges::single_view(2.)); + auto it = v.begin(); + assert(*it == std::make_tuple(1, 0, 2.0)); + + auto const_it = std::as_const(v).begin(); + assert(*const_it == *it); + + static_assert(!std::same_as<decltype(it), decltype(const_it)>); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + assert(*it == std::make_tuple(1)); + auto cit = std::as_const(v).begin(); + assert(*cit == std::make_tuple(1)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + assert(&*it == &buffer[0]); + auto cit = std::as_const(v).begin(); + assert(&*cit == &buffer[0]); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto it = v.begin(); + assert(&std::get<0>(*it) == &buffer[0]); + assert(&std::get<1>(*it) == &buffer[0]); + assert(std::get<2>(*it) == 2.0); + auto cit = std::as_const(v).begin(); + assert(&std::get<0>(*cit) == &buffer[0]); + assert(&std::get<1>(*cit) == &buffer[0]); + assert(std::get<2>(*cit) == 2.0); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // underlying const R is not a range + using ZTV = std::ranges::zip_transform_view<MakeTuple, SimpleCommon, NoConstBeginView>; + static_assert(HasBegin<ZTV>); + static_assert(!HasConstBegin<ZTV>); + } + + { + // Fn cannot be invoked on const range + using ZTV = std::ranges::zip_transform_view<NonConstOnlyFn, ConstNonConstDifferentView>; + static_assert(HasBegin<ZTV>); + static_assert(!HasConstBegin<ZTV>); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/cpo.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/cpo.pass.cpp new file mode 100644 index 0000000..4a0bf7b --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/cpo.pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// 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::views::zip_transform + +#include <ranges> + +#include <algorithm> +#include <array> +#include <cassert> +#include <functional> +#include <type_traits> +#include <vector> + +#include "types.h" + +struct NotMoveConstructible { + NotMoveConstructible() = default; + NotMoveConstructible(NotMoveConstructible&&) = delete; + int operator()() const { return 5; } +}; + +struct NotCopyConstructible { + NotCopyConstructible() = default; + NotCopyConstructible(NotCopyConstructible&&) = default; + NotCopyConstructible(const NotCopyConstructible&) = delete; + int operator()() const { return 5; } +}; + +struct NotInvocable {}; + +template <class... Args> +struct Invocable { + int operator()(Args...) const { return 5; } +}; + +struct ReturnNotObject { + void operator()() const {} +}; + +// LWG3773 views::zip_transform still requires F to be copy_constructible when empty pack +static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), NotCopyConstructible>); + +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform))>); +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), NotMoveConstructible>); +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), NotInvocable>); +static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), Invocable<>>); +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), ReturnNotObject>); + +static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), // + Invocable<int>, // + std::ranges::iota_view<int, int>>); +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), // + Invocable<>, // + std::ranges::iota_view<int, int>>); +static_assert(!std::is_invocable_v<decltype((std::views::zip_transform)), + Invocable<int>, + std::ranges::iota_view<int, int>, + std::ranges::iota_view<int, int>>); +static_assert(std::is_invocable_v<decltype((std::views::zip_transform)), + Invocable<int, int>, + std::ranges::iota_view<int, int>, + std::ranges::iota_view<int, int>>); + +constexpr bool test() { + { + // zip_transform function with no ranges + auto v = std::views::zip_transform(Invocable<>{}); + assert(std::ranges::empty(v)); + static_assert(std::is_same_v<decltype(v), std::ranges::empty_view<int>>); + } + + { + // zip_transform views + int buffer1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + int buffer2[] = {9, 10, 11, 12}; + auto view1 = std::views::all(buffer1); + auto view2 = std::views::all(buffer2); + std::same_as<std::ranges::zip_transform_view<std::plus<>, decltype(view1), decltype(view2)>> decltype(auto) v = + std::views::zip_transform(std::plus{}, buffer1, buffer2); + assert(std::ranges::size(v) == 4); + auto expected = {10, 12, 14, 16}; + assert(std::ranges::equal(v, expected)); + static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v)>, int>); + } + + { + // zip_transform a viewable range + std::array a{1, 2, 3}; + auto id = [](auto& x) -> decltype(auto) { return (x); }; + std::same_as< + std::ranges::zip_transform_view<decltype(id), std::ranges::ref_view<std::array<int, 3>>>> decltype(auto) v = + std::views::zip_transform(id, a); + assert(&v[0] == &a[0]); + static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v)>, int&>); + } + + int buffer[] = {1, 2, 3}; + { + // one range + auto v = std::views::zip_transform(MakeTuple{}, SimpleCommon{buffer}); + assert(std::ranges::equal(v, std::vector{std::tuple(1), std::tuple(2), std::tuple(3)})); + } + + { + // two ranges + auto v = std::views::zip_transform(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + assert(std::ranges::equal(v, std::vector{1, 2, 3})); + } + + { + // three ranges + auto v = std::views::zip_transform(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + assert(std::ranges::equal(v, std::vector{std::tuple(1, 1, 2.0)})); + } + + { + // single empty range + auto v = std::views::zip_transform(MakeTuple{}, std::ranges::empty_view<int>()); + assert(std::ranges::empty(v)); + } + + { + // empty range at the beginning + auto v = std::views::zip_transform( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + assert(std::ranges::empty(v)); + } + + { + // empty range in the middle + auto v = std::views::zip_transform( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + assert(std::ranges::empty(v)); + } + + { + // empty range at the end + auto v = std::views::zip_transform( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + assert(std::ranges::empty(v)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctad.compile.pass.cpp new file mode 100644 index 0000000..9254dd1 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctad.compile.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 + +// template<class F, class... Rs> +// zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>; + +#include <cassert> +#include <ranges> + +#include "types.h" + +struct Container { + int* begin() const; + int* end() const; +}; + +struct Fn { + int operator()(auto&&...) const { return 5; } +}; + +void testCTAD() { + static_assert(std::is_same_v<decltype(std::ranges::zip_transform_view(Fn{}, Container{})), + std::ranges::zip_transform_view<Fn, std::ranges::owning_view<Container>>>); + + static_assert(std::is_same_v<decltype(std::ranges::zip_transform_view(Fn{}, Container{}, IntView{})), + std::ranges::zip_transform_view<Fn, std::ranges::owning_view<Container>, IntView>>); + + Container c{}; + static_assert( + std::is_same_v< + decltype(std::ranges::zip_transform_view(Fn{}, Container{}, IntView{}, c)), + std::ranges:: + zip_transform_view<Fn, std::ranges::owning_view<Container>, IntView, std::ranges::ref_view<Container>>>); +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.default.pass.cpp new file mode 100644 index 0000000..751210f --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.default.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// zip_transform_view() = default; + +#include <ranges> + +#include <cassert> +#include <type_traits> + +#include "types.h" + +constexpr int buff[] = {1, 2, 3}; + +struct DefaultConstructibleView : std::ranges::view_base { + constexpr DefaultConstructibleView() : begin_(buff), end_(buff + 3) {} + constexpr int const* begin() const { return begin_; } + constexpr int const* end() const { return end_; } + +private: + int const* begin_; + int const* end_; +}; + +struct NonDefaultConstructibleView : std::ranges::view_base { + NonDefaultConstructibleView() = delete; + int* begin() const; + int* end() const; +}; + +struct DefaultConstructibleFn { + constexpr int operator()(const auto&... x) const { return (x + ...); } +}; + +struct NonDefaultConstructibleFn { + NonDefaultConstructibleFn() = delete; + constexpr int operator()(const auto&... x) const; +}; + +// The default constructor requires all underlying views to be default constructible. +// It is implicitly required by the zip_view's constructor. +static_assert(std::is_default_constructible_v<std::ranges::zip_transform_view< // + DefaultConstructibleFn, // + DefaultConstructibleView>>); +static_assert(std::is_default_constructible_v<std::ranges::zip_transform_view< // + DefaultConstructibleFn, // + DefaultConstructibleView, + DefaultConstructibleView>>); +static_assert(!std::is_default_constructible_v<std::ranges::zip_transform_view< // + NonDefaultConstructibleFn, // + DefaultConstructibleView>>); +static_assert(!std::is_default_constructible_v<std::ranges::zip_transform_view< // + DefaultConstructibleFn, // + NonDefaultConstructibleView>>); +static_assert(!std::is_default_constructible_v<std::ranges::zip_transform_view< // + DefaultConstructibleFn, // + DefaultConstructibleView, + NonDefaultConstructibleView>>); + +constexpr bool test() { + { + using View = + std::ranges::zip_transform_view<DefaultConstructibleFn, DefaultConstructibleView, DefaultConstructibleView>; + View v = View(); // the default constructor is not explicit + assert(v.size() == 3); + auto it = v.begin(); + assert(*it++ == 2); + assert(*it++ == 4); + assert(*it == 6); + } + + { + // one range + using View = std::ranges::zip_transform_view<MakeTuple, DefaultConstructibleView>; + View v = View(); // the default constructor is not explicit + auto it = v.begin(); + assert(*it == std::make_tuple(1)); + } + + { + // two ranges + using View = std::ranges::zip_transform_view<MakeTuple, DefaultConstructibleView, std::ranges::iota_view<int>>; + View v = View(); // the default constructor is not explicit + auto it = v.begin(); + assert(*it == std::tuple(1, 0)); + } + + { + // three ranges + using View = std::ranges:: + zip_transform_view<MakeTuple, DefaultConstructibleView, DefaultConstructibleView, std::ranges::iota_view<int>>; + View v = View(); // the default constructor is not explicit + auto it = v.begin(); + assert(*it == std::tuple(1, 1, 0)); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the beginning + using View = std::ranges:: + zip_transform_view<MakeTuple, std::ranges::empty_view<int>, DefaultConstructibleView, DefaultConstructibleView>; + View v = View(); // the default constructor is not explicit + assert(v.empty()); + } + + { + // empty range in the middle + using View = + std::ranges::zip_transform_view<MakeTuple, + DefaultConstructibleView, + std::ranges::empty_view<int>, + DefaultConstructibleView, + DefaultConstructibleView>; + View v = View(); // the default constructor is not explicit + assert(v.empty()); + } + + { + // empty range at the end + using View = std::ranges:: + zip_transform_view<MakeTuple, DefaultConstructibleView, DefaultConstructibleView, std::ranges::empty_view<int>>; + View v = View(); // the default constructor is not explicit + assert(v.empty()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.views.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.views.pass.cpp new file mode 100644 index 0000000..5f3b5a3 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/ctor.views.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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 zip_transform_view(F, Views...) + +#include <algorithm> +#include <ranges> +#include <vector> + +#include "types.h" + +struct Fn { + int operator()(auto&&...) const { return 5; } +}; + +template <class T, class... Args> +concept IsImplicitlyConstructible = requires(T val, Args... args) { val = {std::forward<Args>(args)...}; }; + +// test constructor is explicit +static_assert(std::constructible_from<std::ranges::zip_transform_view<Fn, IntView>, Fn, IntView>); +static_assert(!IsImplicitlyConstructible<std::ranges::zip_transform_view<Fn, IntView>, Fn, IntView>); + +static_assert(std::constructible_from<std::ranges::zip_transform_view<Fn, IntView, IntView>, Fn, IntView, IntView>); +static_assert(!IsImplicitlyConstructible<std::ranges::zip_transform_view<Fn, IntView, IntView>, Fn, IntView, IntView>); + +struct MoveAwareView : std::ranges::view_base { + int moves = 0; + constexpr MoveAwareView() = default; + constexpr MoveAwareView(MoveAwareView&& other) : moves(other.moves + 1) { other.moves = 1; } + constexpr MoveAwareView& operator=(MoveAwareView&& other) { + moves = other.moves + 1; + other.moves = 0; + return *this; + } + constexpr const int* begin() const { return &moves; } + constexpr const int* end() const { return &moves + 1; } +}; + +template <class View1, class View2> +constexpr void constructorTest(auto&& buffer1, auto&& buffer2) { + std::ranges::zip_transform_view v{MakeTuple{}, View1{buffer1}, View2{buffer2}}; + auto [i, j] = *v.begin(); + assert(i == buffer1[0]); + assert(j == buffer2[0]); +}; + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + int buffer2[4] = {9, 8, 7, 6}; + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer2}); + assert(std::ranges::equal(v, std::vector{std::tuple(9), std::tuple(8), std::tuple(7), std::tuple(6)})); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + assert(std::ranges::equal(v, std::vector{1, 2, 3, 4, 5, 6, 7, 8})); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer2}, std::ranges::single_view(2.)); + assert(std::ranges::equal(v, std::vector{std::tuple(1, 9, 2.0)})); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + assert(std::ranges::empty(v)); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + assert(std::ranges::empty(v)); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + assert(std::ranges::empty(v)); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + assert(std::ranges::empty(v)); + } + { + // constructor from views + std::ranges::zip_transform_view v( + MakeTuple{}, SizedRandomAccessView{buffer}, std::views::iota(0), std::ranges::single_view(2.)); + auto [i, j, k] = *v.begin(); + assert(i == 1); + assert(j == 0); + assert(k == 2.0); + } + + { + // arguments are moved once + MoveAwareView mv; + std::ranges::zip_transform_view v{MakeTuple{}, std::move(mv), MoveAwareView{}}; + auto [numMoves1, numMoves2] = *v.begin(); + assert(numMoves1 == 3); // one move from the local variable to parameter, one move from parameter to member + assert(numMoves2 == 2); + } + + // input and forward + { + constructorTest<InputCommonView, ForwardSizedView>(buffer, buffer2); + } + + // bidi and random_access + { + constructorTest<BidiCommonView, SizedRandomAccessView>(buffer, buffer2); + } + + // contiguous + { + constructorTest<ContiguousCommonView, ContiguousCommonView>(buffer, buffer2); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/end.pass.cpp new file mode 100644 index 0000000..e6c7094 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/end.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// 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() +// constexpr auto end() const +// requires range<const InnerView> && +// regular_invocable<const F&, range_reference_t<const Views>...>; + +#include <ranges> + +#include "types.h" + +template <class T> +concept HasConstEnd = requires(const T& ct) { ct.end(); }; + +template <class T> +concept HasEnd = requires(T& t) { t.end(); }; + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + { + // simple test + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::views::iota(0), std::ranges::single_view(2.)); + assert(v.begin() != v.end()); + assert(std::as_const(v).begin() != std::as_const(v).end()); + assert(v.begin() + 1 == v.end()); + assert(std::as_const(v).begin() + 1 == std::as_const(v).end()); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + assert(it + 8 == v.end()); + assert(it + 8 == std::as_const(v).end()); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + assert(it + 8 == v.end()); + assert(it + 8 == std::as_const(v).end()); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto it = v.begin(); + assert(it + 1 == v.end()); + assert(it + 1 == std::as_const(v).end()); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // common_range<InnerView> + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + auto const_it = std::as_const(v).begin(); + auto st = v.end(); + auto const_st = std::as_const(v).end(); + + static_assert(!std::same_as<decltype(it), decltype(const_it)>); + static_assert(!std::same_as<decltype(st), decltype(const_st)>); + static_assert(std::same_as<decltype(it), decltype(st)>); + static_assert(std::same_as<decltype(const_it), decltype(const_st)>); + + assert(it + 8 == st); + assert(const_it + 8 == const_st); + } + { + // !common_range<InnerView> + std::ranges::zip_transform_view v(MakeTuple{}, SimpleNonCommon{buffer}); + auto it = v.begin(); + auto const_it = std::as_const(v).begin(); + auto st = v.end(); + auto const_st = std::as_const(v).end(); + + static_assert(!std::same_as<decltype(it), decltype(const_it)>); + static_assert(!std::same_as<decltype(st), decltype(const_st)>); + static_assert(!std::same_as<decltype(it), decltype(st)>); + static_assert(!std::same_as<decltype(const_it), decltype(const_st)>); + + assert(it + 8 == st); + assert(const_it + 8 == const_st); + } + + { + // underlying const R is not a range + using ZTV = std::ranges::zip_transform_view<MakeTuple, SimpleCommon, NoConstBeginView>; + static_assert(HasEnd<ZTV>); + static_assert(!HasConstEnd<ZTV>); + } + + { + // Fn cannot invoke on const range + using ZTV = std::ranges::zip_transform_view<NonConstOnlyFn, ConstNonConstDifferentView>; + static_assert(HasEnd<ZTV>); + static_assert(!HasConstEnd<ZTV>); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/general.pass.cpp new file mode 100644 index 0000000..3c35de2 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/general.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 + +// Some basic examples of how zip_tranform_view might be used in the wild. This is a general +// collection of sample algorithms and functions that try to mock general usage of +// this view. + +#include <ranges> + +#include <algorithm> +#include <cassert> +#include <functional> +#include <vector> + +int main(int, char**) { + std::vector v1 = {1, 2}; + std::vector v2 = {4, 5, 6}; + auto ztv = std::views::zip_transform(std::plus(), v1, v2); + auto expected = {5, 7}; + assert(std::ranges::equal(ztv, expected)); + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/arithmetic.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/arithmetic.pass.cpp new file mode 100644 index 0000000..d697ae5 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/arithmetic.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// 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 x) requires random_access_range<Base>; +// constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; +// friend constexpr iterator operator+(const iterator& i, difference_type n) +// requires random_access_range<Base>; +// friend constexpr iterator operator+(difference_type n, const iterator& i) +// requires random_access_range<Base>; +// friend constexpr iterator operator-(const iterator& i, difference_type n) +// requires random_access_range<Base>; +// friend constexpr difference_type operator-(const iterator& x, const iterator& y) +// requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>; + +#include <ranges> + +#include <array> +#include <concepts> +#include <functional> + +#include "../types.h" + +template <class T, class U> +concept canPlusEqual = requires(T& t, U& u) { t += u; }; + +template <class T, class U> +concept canPlus = requires(T& t, U& u) { t + u; }; + +template <class T, class U> +concept canMinusEqual = requires(T& t, U& u) { t -= u; }; + +template <class T, class U> +concept canMinus = requires(T& t, U& u) { t - u; }; + +constexpr bool test() { + int buffer1[5] = {1, 2, 3, 4, 5}; + SizedRandomAccessView a{buffer1}; + static_assert(std::ranges::random_access_range<decltype(a)>); + + std::array b{4.1, 3.2, 4.3, 0.1, 0.2}; + static_assert(std::ranges::contiguous_range<decltype(b)>); + + { + // operator+(x, n) and operator+= + std::ranges::zip_transform_view v(MakeTuple{}, a, b); + auto it1 = v.begin(); + using Iter = decltype(it1); + + std::same_as<Iter> decltype(auto) it2 = it1 + 3; + assert(*it2 == std::tuple(4, 0.1)); + + std::same_as<Iter> decltype(auto) it3 = 3 + it1; + assert(*it3 == std::tuple(4, 0.1)); + + std::same_as<Iter&> decltype(auto) it1_ref = it1 += 3; + assert(&it1_ref == &it1); + assert(*it1_ref == std::tuple(4, 0.1)); + assert(*it1 == std::tuple(4, 0.1)); + + static_assert(canPlus<Iter, std::intptr_t>); + static_assert(canPlusEqual<Iter, std::intptr_t>); + } + + { + // operator-(x, n) and operator-= + std::ranges::zip_transform_view v(MakeTuple{}, a, b); + auto it1 = v.end(); + using Iter = decltype(it1); + + std::same_as<Iter> decltype(auto) it2 = it1 - 3; + assert(*it2 == std::tuple(3, 4.3)); + + std::same_as<Iter&> decltype(auto) it1_ref = it1 -= 3; + assert(&it1_ref == &it1); + assert(*it1_ref == std::tuple(3, 4.3)); + assert(*it1 == std::tuple(3, 4.3)); + + static_assert(canMinusEqual<Iter, std::intptr_t>); + static_assert(canMinus<Iter, std::intptr_t>); + } + + { + // operator-(x, y) + std::ranges::zip_transform_view v(MakeTuple{}, a, b); + assert((v.end() - v.begin()) == 5); + + auto it1 = v.begin() + 2; + auto it2 = v.end() - 1; + + using Iter = decltype(it1); + + std::same_as<std::iter_difference_t<Iter>> decltype(auto) n = it1 - it2; + assert(n == -2); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer1}); + auto it = v.begin(); + assert(*it == std::make_tuple(1)); + + it += 4; + assert(*it == std::make_tuple(5)); + + it -= 1; + assert(*it == std::make_tuple(4)); + + auto it2 = it - 2; + assert(*it2 == std::make_tuple(2)); + + auto it3 = 3 + it2; + assert(*it3 == std::make_tuple(5)); + + assert(it3 - it2 == 3); + } + + { + // two ranges + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer1}, std::views::iota(0)); + auto it = v.begin(); + assert(*it == std::make_tuple(1, 0)); + + it += 4; + assert(*it == std::make_tuple(5, 4)); + + it -= 1; + assert(*it == std::make_tuple(4, 3)); + + auto it2 = it - 2; + assert(*it2 == std::make_tuple(2, 1)); + + auto it3 = 3 + it2; + assert(*it3 == std::make_tuple(5, 4)); + + assert(it3 - it2 == 3); + } + + { + // three ranges + std::ranges::zip_transform_view v( + Tie{}, SimpleCommon{buffer1}, SimpleCommon{buffer1}, std::ranges::single_view(2.)); + auto it = v.begin(); + assert(*it == std::make_tuple(1, 1, 2.0)); + + it += 1; + assert(it == v.end()); + + it -= 1; + assert(it == v.begin()); + + auto it2 = it + 1; + assert(it2 == v.end()); + + auto it3 = it2 - 1; + assert(it3 == v.begin()); + + assert(it3 - it2 == -1); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + auto it = v.begin(); + auto it2 = v.end(); + assert(it2 - it == 0); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer1}, SimpleCommon{buffer1}); + auto it = v.begin(); + auto it2 = v.end(); + assert(it2 - it == 0); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, std::ranges::empty_view<int>(), SimpleCommon{buffer1}); + auto it = v.begin(); + auto it2 = v.end(); + assert(it2 - it == 0); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, SimpleCommon{buffer1}, std::ranges::empty_view<int>()); + auto it = v.begin(); + auto it2 = v.end(); + assert(it2 - it == 0); + } + { + // One of the ranges is not random access + std::ranges::zip_transform_view v(MakeTuple{}, a, b, ForwardSizedView{buffer1}); + auto it1 = v.begin(); + using Iter = decltype(it1); + static_assert(!canPlus<Iter, std::intptr_t>); + static_assert(!canPlus<std::intptr_t, Iter>); + static_assert(!canPlusEqual<Iter, std::intptr_t>); + static_assert(!canMinus<Iter, std::intptr_t>); + static_assert(canMinus<Iter, Iter>); + static_assert(!canMinusEqual<Iter, std::intptr_t>); + + auto it2 = ++v.begin(); + assert((it2 - it1) == 1); + } + + { + // One of the ranges does not have sized sentinel + std::ranges::zip_transform_view v(MakeTuple{}, a, b, InputCommonView{buffer1}); + using Iter = decltype(v.begin()); + static_assert(!canPlus<Iter, std::intptr_t>); + static_assert(!canPlus<std::intptr_t, Iter>); + static_assert(!canPlusEqual<Iter, std::intptr_t>); + static_assert(!canMinus<Iter, std::intptr_t>); + static_assert(!canMinus<Iter, Iter>); + static_assert(!canMinusEqual<Iter, std::intptr_t>); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/compare.pass.cpp new file mode 100644 index 0000000..2befb7e --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/compare.pass.cpp @@ -0,0 +1,226 @@ +//===----------------------------------------------------------------------===// +// +// 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 bool operator==(const iterator& x, const iterator& y) +// requires equality_comparable<ziperator<Const>>; + +// friend constexpr auto operator<=>(const iterator& x, const iterator& y) +// requires random_access_range<Base>; + +#include <ranges> + +#include <compare> + +#include "test_iterators.h" +#include "../types.h" + +constexpr void compareOperatorTest(auto&& iter1, auto&& iter2) { + assert(!(iter1 < iter1)); + assert(iter1 < iter2); + assert(!(iter2 < iter1)); + assert(iter1 <= iter1); + assert(iter1 <= iter2); + assert(!(iter2 <= iter1)); + assert(!(iter1 > iter1)); + assert(!(iter1 > iter2)); + assert(iter2 > iter1); + assert(iter1 >= iter1); + assert(!(iter1 >= iter2)); + assert(iter2 >= iter1); + assert(iter1 == iter1); + assert(!(iter1 == iter2)); + assert(iter2 == iter2); + assert(!(iter1 != iter1)); + assert(iter1 != iter2); + assert(!(iter2 != iter2)); +} + +constexpr void spaceshipTest(auto&& iter1, auto&& iter2) { + using Iter = decltype(iter1); + static_assert(std::three_way_comparable<Iter>); + assert((iter1 <=> iter2) == std::strong_ordering::less); + assert((iter1 <=> iter1) == std::strong_ordering::equal); + assert((iter2 <=> iter2) == std::strong_ordering::equal); + assert((iter2 <=> iter1) == std::strong_ordering::greater); +} + +constexpr void inequalityOperatorsDoNotExistTest(auto&& iter1, auto&& iter2) { + using Iter1 = decltype(iter1); + using Iter2 = decltype(iter2); + static_assert(!std::is_invocable_v<std::less<>, Iter1, Iter2>); + static_assert(!std::is_invocable_v<std::less_equal<>, Iter1, Iter2>); + static_assert(!std::is_invocable_v<std::greater<>, Iter1, Iter2>); + static_assert(!std::is_invocable_v<std::greater_equal<>, Iter1, Iter2>); +} + +constexpr bool test() { + { + // Test a new-school iterator with operator<=>; the iterator should also have operator<=>. + using It = three_way_contiguous_iterator<int*>; + using SubRange = std::ranges::subrange<It>; + static_assert(std::three_way_comparable<It>); + + int a[] = {1, 2, 3, 4}; + int b[] = {5, 6, 7, 8, 9}; + auto r = std::views::zip_transform(MakeTuple{}, SubRange(It(a), It(a + 4)), SubRange(It(b), It(b + 5))); + auto iter1 = r.begin(); + auto iter2 = iter1 + 1; + using Iter = decltype(iter1); + static_assert(std::three_way_comparable<Iter>); + compareOperatorTest(iter1, iter2); + spaceshipTest(iter1, iter2); + } + + { + // Test an old-school iterator with no operator<=>; the transform iterator shouldn't have + // operator<=> either. + using It = random_access_iterator<int*>; + using Subrange = std::ranges::subrange<It>; + static_assert(!std::three_way_comparable<It>); + + int a[] = {1, 2, 3, 4}; + int b[] = {5, 6, 7, 8, 9}; + auto r = std::views::zip_transform(MakeTuple{}, Subrange(It(a), It(a + 4)), Subrange(It(b), It(b + 5))); + auto iter1 = r.begin(); + auto iter2 = iter1 + 1; + + compareOperatorTest(iter1, iter2); + spaceshipTest(iter1, iter2); + } + + int buffer[5] = {1, 2, 3, 4, 5}; + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + auto it2 = it + 3; + compareOperatorTest(it, it2); + spaceshipTest(it, it2); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + auto it2 = it + 3; + compareOperatorTest(it, it2); + spaceshipTest(it, it2); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto it = v.begin(); + auto it2 = it + 1; + compareOperatorTest(it, it2); + spaceshipTest(it, it2); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + auto it = v.begin(); + auto it2 = v.end(); + assert(it == it2); + assert(it <=> it2 == std::strong_ordering::equal); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + auto it = v.begin(); + auto it2 = v.end(); + assert(it == it2); + assert(it <=> it2 == std::strong_ordering::equal); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + auto it = v.begin(); + auto it2 = v.end(); + assert(it == it2); + assert(it <=> it2 == std::strong_ordering::equal); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + auto it = v.begin(); + auto it2 = v.end(); + assert(it == it2); + assert(it <=> it2 == std::strong_ordering::equal); + } + + { + // non random_access_range + int buffer1[1] = {1}; + int buffer2[2] = {1, 2}; + + std::ranges::zip_transform_view v{MakeTuple{}, InputCommonView(buffer1), InputCommonView(buffer2)}; + using ZTV = decltype(v); + static_assert(!std::ranges::forward_range<ZTV>); + static_assert(std::ranges::input_range<ZTV>); + static_assert(std::ranges::common_range<ZTV>); + + auto it1 = v.begin(); + auto it2 = v.end(); + assert(it1 != it2); + + ++it1; + assert(it1 == it2); + + inequalityOperatorsDoNotExistTest(it1, it2); + } + + { + // in this case sentinel is computed by getting each of the underlying sentinel, so only one + // underlying iterator is comparing equal + int buffer1[1] = {1}; + int buffer2[2] = {1, 2}; + std::ranges::zip_transform_view v{MakeTuple{}, ForwardSizedView(buffer1), ForwardSizedView(buffer2)}; + using ZTV = decltype(v); + static_assert(std::ranges::common_range<ZTV>); + static_assert(!std::ranges::bidirectional_range<ZTV>); + + auto it1 = v.begin(); + auto it2 = v.end(); + assert(it1 != it2); + + ++it1; + // it1: <buffer1 + 1, buffer2 + 1> + // it2: <buffer1 + 1, buffer2 + 2> + assert(it1 == it2); + + inequalityOperatorsDoNotExistTest(it1, it2); + } + + { + // underlying iterator does not support == + using IterNoEqualView = BasicView<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>; + int buffer2[] = {1}; + std::ranges::zip_transform_view r(MakeTuple{}, IterNoEqualView{buffer2}); + auto it = r.begin(); + using Iter = decltype(it); + static_assert(!std::invocable<std::equal_to<>, Iter, Iter>); + inequalityOperatorsDoNotExistTest(it, it); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.default.pass.cpp new file mode 100644 index 0000000..8f8369d --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.default.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 <ranges> + +#include "../types.h" + +struct IterDefaultCtrView : std::ranges::view_base { + int* begin() const; + int* end() const; +}; + +struct IterNoDefaultCtrView : std::ranges::view_base { + cpp20_input_iterator<int*> begin() const; + sentinel_wrapper<cpp20_input_iterator<int*>> end() const; +}; + +template <class... Views> +using Iter = std::ranges::iterator_t<std::ranges::zip_transform_view<MakeTuple, Views...>>; + +static_assert(!std::default_initializable<Iter<IterNoDefaultCtrView>>); +static_assert(!std::default_initializable<Iter<IterNoDefaultCtrView, IterDefaultCtrView>>); +static_assert(!std::default_initializable<Iter<IterNoDefaultCtrView, IterNoDefaultCtrView>>); +static_assert(std::default_initializable<Iter<IterDefaultCtrView>>); +static_assert(std::default_initializable<Iter<IterDefaultCtrView, IterDefaultCtrView>>); + +template <class Fn, class... Views> +constexpr void test() { + using ZipTransformIter = std::ranges::iterator_t<std::ranges::zip_transform_view<Fn, Views...>>; + ZipTransformIter iter1 = {}; + ZipTransformIter iter2; + assert(iter1 == iter2); +} + +constexpr bool test() { + test<MakeTuple, IterDefaultCtrView>(); + test<MakeTuple, IterDefaultCtrView, std::ranges::empty_view<int>>(); + test<MakeTuple, IterDefaultCtrView, std::ranges::iota_view<int>, std::ranges::single_view<int>>(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.other.pass.cpp new file mode 100644 index 0000000..c643d83 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/ctor.other.pass.cpp @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// +// 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(iterator<!Const> i) +// requires Const && convertible_to<ziperator<false>, ziperator<Const>>; + +#include <array> +#include <ranges> + +#include <cassert> + +#include "../types.h" + +using ConstIterIncompatibleView = + BasicView<forward_iterator<int*>, + forward_iterator<int*>, + random_access_iterator<const int*>, + random_access_iterator<const int*>>; +static_assert(!std::convertible_to<std::ranges::iterator_t<ConstIterIncompatibleView>, + std::ranges::iterator_t<const ConstIterIncompatibleView>>); + +constexpr bool test() { + int buffer[3] = {1, 2, 3}; + + { + std::ranges::zip_transform_view v(MakeTuple{}, NonSimpleCommon{buffer}); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + assert(iter1 == iter2); + + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + + // We cannot create a non-const iterator from a const iterator. + static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>); + } + + { + // Check when we can't perform a non-const-to-const conversion of the ziperator + std::ranges::zip_transform_view v(MakeTuple{}, ConstIterIncompatibleView{buffer}); + auto iter1 = v.begin(); + auto iter2 = std::as_const(v).begin(); + + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + + static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>); + static_assert(!std::constructible_from<decltype(iter2), decltype(iter1)>); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, NonSimpleCommon{buffer}); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(*iter2 == std::tuple(1)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, NonSimpleCommon{buffer}, std::views::iota(0)); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(*iter2 == 1); + } + + { + // three ranges + std::ranges::zip_transform_view v( + Tie{}, NonSimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(*iter2 == std::tuple(1, 1, 2.0)); + } + + { + // single empty range + std::array<int, 0> buffer2{}; + std::ranges::zip_transform_view v(MakeTuple{}, buffer2); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(iter2 == v.end()); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), NonSimpleCommon{buffer}, SimpleCommon{buffer}); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(iter2 == v.end()); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), NonSimpleCommon{buffer}); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(iter2 == v.end()); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, NonSimpleCommon{buffer}, std::ranges::empty_view<int>()); + auto iter1 = v.begin(); + std::ranges::iterator_t<const decltype(v)> iter2 = iter1; + static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>); + assert(iter2 == v.end()); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/decrement.pass.cpp new file mode 100644 index 0000000..9f3647b --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/decrement.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// 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--() requires bidirectional_range<Base>; +// constexpr iterator operator--(int) requires bidirectional_range<Base>; + +#include <array> +#include <cassert> +#include <ranges> + +#include "../types.h" + +template <class Iter> +concept canDecrement = requires(Iter it) { --it; } || requires(Iter it) { it--; }; + +constexpr bool test() { + std::array a{1, 2, 3, 4}; + std::array b{4.1, 3.2, 4.3}; + { + // all random access + std::ranges::zip_transform_view v(MakeTuple{}, a, b, std::views::iota(0, 5)); + auto it = v.end(); + using Iter = decltype(it); + static_assert(canDecrement<Iter>); + + std::same_as<Iter&> decltype(auto) it_ref = --it; + assert(&it_ref == &it); + + assert(*it == std::tuple(3, 4.3, 2)); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it--; + assert(original == it2); + assert(*it == std::tuple(2, 3.2, 1)); + } + + { + // all bidi+ + int buffer[2] = {1, 2}; + + std::ranges::zip_transform_view v(MakeTuple{}, BidiCommonView{buffer}, std::views::iota(0, 5)); + auto it = v.begin(); + using Iter = decltype(it); + static_assert(canDecrement<Iter>); + + ++it; + ++it; + + std::same_as<Iter&> decltype(auto) it_ref = --it; + assert(&it_ref == &it); + + assert(it == ++v.begin()); + assert(*it == std::tuple(2, 1)); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it--; + assert(original == it2); + assert(*it == std::tuple(1, 0)); + } + + { + // non bidi + int buffer[3] = {4, 5, 6}; + std::ranges::zip_transform_view v(MakeTuple{}, a, InputCommonView{buffer}); + using Iter = std::ranges::iterator_t<decltype(v)>; + static_assert(!canDecrement<Iter>); + } + + int buffer[] = {1, 2, 3, 4, 5, 6}; + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.end(); + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = --it; + assert(&it_ref == &it); + + assert(*it == std::tuple(6)); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it--; + assert(original == it2); + assert(*it == std::tuple(5)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin() + 5; + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = --it; + assert(&it_ref == &it); + + assert(*it == 5); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it--; + assert(original == it2); + assert(*it == 4); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto it = v.end(); + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = --it; + assert(&it_ref == &it); + + assert(*it == std::tuple(1, 1, 2.0)); + + ++it; + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it--; + assert(original == it2); + assert(*it == std::tuple(1, 1, 2.0)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/deref.pass.cpp new file mode 100644 index 0000000..3c97e11 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/deref.pass.cpp @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// 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 decltype(auto) operator*() const noexcept(see below); + +#include <array> +#include <cassert> +#include <ranges> + +#include "../types.h" + +// Test noexcept +// Remarks: Let Is be the pack 0, 1, ..., (sizeof...(Views)-1). The exception specification is equivalent to: +// noexcept(invoke(*parent_->fun_, *std::get<Is>(inner_.current_)...)). + +template <class ZipTransformView> +concept DerefNoexcept = requires(std::ranges::iterator_t<ZipTransformView> iter) { requires noexcept(*iter); }; + +struct ThrowingDerefIter { + using iterator_category = std::forward_iterator_tag; + using value_type = int; + using difference_type = std::intptr_t; + + int operator*() const noexcept(false); + + ThrowingDerefIter& operator++(); + void operator++(int); + + friend constexpr bool operator==(const ThrowingDerefIter&, const ThrowingDerefIter&) = default; +}; + +using NoexceptDerefIter = int*; + +template <bool NoExceptDeref> +struct TestView : std::ranges::view_base { + using Iter = std::conditional_t<NoExceptDeref, NoexceptDerefIter, ThrowingDerefIter>; + Iter begin() const; + Iter end() const; +}; + +template <bool NoExceptCall> +struct TestFn { + int operator()(auto&&...) const noexcept(NoExceptCall); +}; + +static_assert(DerefNoexcept<std::ranges::zip_transform_view<TestFn<true>, TestView<true>>>); +static_assert(DerefNoexcept<std::ranges::zip_transform_view<TestFn<true>, TestView<true>, TestView<true>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<true>, TestView<false>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<false>, TestView<true>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<false>, TestView<false>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<false>, TestView<false>, TestView<true>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<true>, TestView<false>, TestView<true>>>); +static_assert(!DerefNoexcept<std::ranges::zip_transform_view<TestFn<false>, TestView<false>, TestView<false>>>); + +constexpr bool test() { + std::array a{1, 2, 3, 4}; + std::array b{4.1, 3.2, 4.3}; + { + // Function returns reference + std::ranges::zip_transform_view v(GetFirst{}, a); + auto it = v.begin(); + std::same_as<int&> decltype(auto) val = *it; + assert(&val == &a[0]); + } + + { + // function returns PRValue + std::ranges::zip_transform_view v(MakeTuple{}, a, b); + auto it = v.begin(); + std::same_as<std::tuple<int, double>> decltype(auto) val = *it; + assert(val == std::tuple(1, 4.1)); + } + + { + // operator* is const + std::ranges::zip_transform_view v(GetFirst{}, a); + const auto it = v.begin(); + std::same_as<int&> decltype(auto) val = *it; + assert(&val == &a[0]); + } + + { + // dereference twice + std::ranges::zip_transform_view v(MakeTuple{}, a, b); + auto it = v.begin(); + assert(*it == std::tuple(1, 4.1)); + assert(*it == std::tuple(1, 4.1)); + } + + { + // back and forth + std::ranges::zip_transform_view v(Tie{}, a, b); + auto it = v.begin(); + assert(&std::get<0>(*it) == &a[0]); + assert(&std::get<1>(*it) == &b[0]); + ++it; + assert(&std::get<0>(*it) == &a[1]); + assert(&std::get<1>(*it) == &b[1]); + --it; + assert(&std::get<0>(*it) == &a[0]); + assert(&std::get<1>(*it) == &b[0]); + } + + int buffer[] = {1, 2, 3, 4, 5, 6}; + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + assert(*it == std::make_tuple(1)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + assert(&*it == &buffer[0]); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::single_view(2.)); + auto it = v.begin(); + assert(&std::get<0>(*it) == &buffer[0]); + assert(&std::get<1>(*it) == &buffer[0]); + assert(std::get<2>(*it) == 2.0); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/increment.pass.cpp new file mode 100644 index 0000000..4a1ec74 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/increment.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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); +// constexpr iterator operator++(int) requires forward_range<Base>;; + +#include <array> +#include <cassert> +#include <ranges> + +#include "../types.h" + +struct InputRange : IntBufferView { + using IntBufferView::IntBufferView; + using iterator = cpp20_input_iterator<int*>; + constexpr iterator begin() const { return iterator(buffer_); } + constexpr sentinel_wrapper<iterator> end() const { return sentinel_wrapper<iterator>(iterator(buffer_ + size_)); } +}; + +template <class View> +constexpr void testForwardPlus() { + int buffer[] = {1, 2, 3, 4}; + + std::ranges::zip_transform_view v(GetFirst{}, View{buffer}, View{buffer}); + auto it = v.begin(); + using Iter = decltype(it); + + assert(&(*it) == &(buffer[0])); + + std::same_as<Iter&> decltype(auto) it_ref = ++it; + assert(&it_ref == &it); + assert(&(*it) == &(buffer[1])); + + static_assert(std::is_same_v<decltype(it++), Iter>); + auto original = it; + std::same_as<Iter> decltype(auto) copy = it++; + assert(original == copy); + assert(&(*it) == &(buffer[2])); +} + +constexpr bool test() { + testForwardPlus<SizedRandomAccessView>(); + testForwardPlus<BidiCommonView>(); + testForwardPlus<ForwardSizedView>(); + + { + // test input_range + int buffer[3] = {4, 5, 6}; + std::ranges::zip_transform_view v(MakeTuple{}, InputRange{buffer}, InputRange{buffer}); + auto it = v.begin(); + using Iter = decltype(it); + + assert(*it == std::tuple(4, 4)); + + std::same_as<Iter&> decltype(auto) it_ref = ++it; + assert(&it_ref == &it); + assert(*it == std::tuple(5, 5)); + + static_assert(std::is_same_v<decltype(it++), void>); + it++; + assert(*it == std::tuple(6, 6)); + } + + int buffer[] = {1, 2, 3, 4, 5, 6}; + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = ++it; + assert(&it_ref == &it); + + assert(*it == std::tuple(2)); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it++; + assert(original == it2); + assert(*it == std::tuple(3)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = ++it; + assert(&it_ref == &it); + + assert(*it == 2); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it++; + assert(original == it2); + assert(*it == 3); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::repeat_view(2.)); + auto it = v.begin(); + using Iter = decltype(it); + + std::same_as<Iter&> decltype(auto) it_ref = ++it; + assert(&it_ref == &it); + + assert(*it == std::tuple(2, 2, 2.0)); + + auto original = it; + std::same_as<Iter> decltype(auto) it2 = it++; + assert(original == it2); + assert(*it == std::tuple(3, 3, 2.0)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/member_types.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/member_types.compile.pass.cpp new file mode 100644 index 0000000..222f9e4 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/member_types.compile.pass.cpp @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// +// 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 traits and member typedefs in zip_transform_view::iterator. + +#include <array> +#include <ranges> + +#include "test_iterators.h" + +#include "../types.h" + +template <class T> +concept HasIterCategory = requires { typename T::iterator_category; }; + +template <class T> +struct DiffTypeIter { + using iterator_category = std::input_iterator_tag; + using value_type = int; + using difference_type = T; + + int operator*() const; + DiffTypeIter& operator++(); + void operator++(int); + friend constexpr bool operator==(DiffTypeIter, DiffTypeIter) = default; +}; + +template <class T> +struct DiffTypeRange { + DiffTypeIter<T> begin() const; + DiffTypeIter<T> end() const; +}; + +struct Foo {}; +struct Bar {}; + +struct RValueRefFn { + int&& operator()(auto&&...) const; +}; + +void test() { + int buffer[] = {1, 2, 3, 4}; + { + // C++20 random_access C++17 random_access + std::ranges::zip_transform_view v(GetFirst{}, buffer); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::random_access_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, int>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 random_access C++17 input + std::ranges::zip_transform_view v(MakeTuple{}, buffer); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, std::tuple<int>>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 bidirectional C++17 bidirectional + std::ranges::zip_transform_view v(GetFirst{}, BidiCommonView{buffer}); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::bidirectional_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::bidirectional_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, int>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 bidirectional C++17 input + std::ranges::zip_transform_view v(MakeTuple{}, BidiCommonView{buffer}); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::bidirectional_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, std::tuple<int>>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 forward C++17 bidirectional + std::ranges::zip_transform_view v(GetFirst{}, ForwardSizedView{buffer}); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::forward_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::forward_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, int>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 forward C++17 input + std::ranges::zip_transform_view v(MakeTuple{}, ForwardSizedView{buffer}); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::forward_iterator_tag>); + static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, std::tuple<int>>); + static_assert(HasIterCategory<Iter>); + } + + { + // C++20 input C++17 not a range + std::ranges::zip_transform_view v(GetFirst{}, InputCommonView{buffer}); + using Iter = decltype(v.begin()); + + static_assert(std::is_same_v<Iter::iterator_concept, std::input_iterator_tag>); + static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); + static_assert(std::is_same_v<Iter::value_type, int>); + static_assert(!HasIterCategory<Iter>); + } + + { + // difference_type of one view + std::ranges::zip_transform_view v{MakeTuple{}, DiffTypeRange<std::intptr_t>{}}; + using Iter = decltype(v.begin()); + static_assert(std::is_same_v<Iter::difference_type, std::intptr_t>); + } + + { + // difference_type of multiple views should be the common type + std::ranges::zip_transform_view v{MakeTuple{}, DiffTypeRange<std::intptr_t>{}, DiffTypeRange<std::ptrdiff_t>{}}; + using Iter = decltype(v.begin()); + static_assert(std::is_same_v<Iter::difference_type, std::common_type_t<std::intptr_t, std::ptrdiff_t>>); + } + + const std::array foos{Foo{}}; + std::array bars{Bar{}, Bar{}}; + { + // value_type of one view + std::ranges::zip_transform_view v{MakeTuple{}, foos}; + using Iter = decltype(v.begin()); + static_assert(std::is_same_v<Iter::value_type, std::tuple<Foo>>); + } + + { + // value_type of multiple views with different value_type + std::ranges::zip_transform_view v{MakeTuple{}, foos, bars}; + using Iter = decltype(v.begin()); + static_assert(std::is_same_v<Iter::value_type, std::tuple<Foo, Bar>>); + } + + // LWG3798 Rvalue reference and iterator_category + { + std::ranges::zip_transform_view v(RValueRefFn{}, buffer); + using Iter = decltype(v.begin()); + static_assert(std::is_same_v<Iter::iterator_category, std::random_access_iterator_tag>); + } +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/subscript.pass.cpp new file mode 100644 index 0000000..70cf811 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/iterator/subscript.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// 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 decltype(auto) operator[](difference_type n) const +// requires random_access_range<Base>; + +#include <ranges> +#include <cassert> + +#include "../types.h" + +template <class T> +concept CanSubscript = requires(T t) { t[0]; }; + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + // F returns PR value + std::ranges::zip_transform_view v(MakeTuple{}, SizedRandomAccessView{buffer}, std::views::iota(0)); + auto it = v.begin(); + using Iter = decltype(it); + static_assert(CanSubscript<Iter>); + + std::same_as<std::tuple<int, int>> decltype(auto) val = it[0]; + assert(val == *it); + assert(it[2] == *(it + 2)); + assert(it[4] == *(it + 4)); + } + + { + // F return by reference + std::ranges::zip_transform_view v(GetFirst{}, ContiguousCommonView{buffer}, ContiguousCommonView{buffer}); + auto it = v.begin(); + using Iter = decltype(it); + static_assert(CanSubscript<Iter>); + + std::same_as<int&> decltype(auto) val = it[0]; + assert(&val == &buffer[0]); + assert(val == *it); + assert(it[2] == *(it + 2)); + assert(it[4] == *(it + 4)); + } + + { + // non random_access_range + std::ranges::zip_transform_view v(GetFirst{}, BidiCommonView{buffer}); + auto it = v.begin(); + using Iter = decltype(it); + static_assert(!CanSubscript<Iter>); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + auto it = v.begin(); + assert(it[2] == std::make_tuple(3)); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, std::views::iota(0)); + auto it = v.begin(); + assert(it[0] == 1); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::repeat_view(2.)); + auto it = v.begin(); + assert(&std::get<0>(it[1]) == &buffer[1]); + assert(&std::get<1>(it[2]) == &buffer[2]); + assert(std::get<2>(it[3]) == 2.0); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.default.pass.cpp new file mode 100644 index 0000000..ab00663 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.default.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 + +// sentinel() = default; + +#include <cassert> +#include <ranges> + +#include "../types.h" + +struct PODSentinel { + bool b; // deliberately uninitialised + + friend constexpr bool operator==(int*, const PODSentinel& s) { return s.b; } +}; + +struct Fn { + int operator()(auto&&...) const { return 5; } +}; + +struct Range : std::ranges::view_base { + int* begin() const; + PODSentinel end(); +}; + +constexpr bool test() { + { + using R = std::ranges::zip_transform_view<Fn, Range>; + using Sentinel = std::ranges::sentinel_t<R>; + static_assert(!std::is_same_v<Sentinel, std::ranges::iterator_t<R>>); + + std::ranges::iterator_t<R> it; + + Sentinel s1; + assert(it != s1); // PODSentinel.b is initialised to false + + Sentinel s2 = {}; + assert(it != s2); // PODSentinel.b is initialised to false + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.other.pass.cpp new file mode 100644 index 0000000..be7c3d1 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/ctor.other.pass.cpp @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// 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 sentinel(sentinel<!Const> i) +// requires Const && convertible_to<zentinel<false>, zentinel<Const>>; + +#include <cassert> +#include <ranges> + +#include "../types.h" + +template <class T> +struct convertible_sentinel_wrapper { + explicit convertible_sentinel_wrapper() = default; + constexpr convertible_sentinel_wrapper(const T& it) : it_(it) {} + + template <class U> + requires std::convertible_to<const U&, T> + constexpr convertible_sentinel_wrapper(const convertible_sentinel_wrapper<U>& other) : it_(other.it_) {} + + constexpr friend bool operator==(convertible_sentinel_wrapper const& self, const T& other) { + return self.it_ == other; + } + T it_; +}; + +struct NonSimpleNonCommonConvertibleView : IntBufferView { + using IntBufferView::IntBufferView; + + constexpr int* begin() { return buffer_; } + constexpr const int* begin() const { return buffer_; } + constexpr convertible_sentinel_wrapper<int*> end() { return convertible_sentinel_wrapper<int*>(buffer_ + size_); } + constexpr convertible_sentinel_wrapper<const int*> end() const { + return convertible_sentinel_wrapper<const int*>(buffer_ + size_); + } +}; + +// convertible_to<zentinel<false>, zentinel<Const>> +static_assert(std::convertible_to< // + std::ranges::sentinel_t<std::ranges::zip_view<NonSimpleNonCommonConvertibleView>>, + std::ranges::sentinel_t<std::ranges::zip_view<NonSimpleNonCommonConvertibleView> const>>); + +constexpr bool test() { + int buffer1[4] = {1, 2, 3, 4}; + int buffer2[5] = {1, 2, 3, 4, 5}; + { + std::ranges::zip_transform_view v{ + MakeTuple{}, NonSimpleNonCommonConvertibleView(buffer1), NonSimpleNonCommonConvertibleView(buffer2)}; + using ZipTransformView = decltype(v); + static_assert(!std::ranges::common_range<ZipTransformView>); + auto sent1 = v.end(); + std::ranges::sentinel_t<const ZipTransformView> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + + assert(v.begin() != sent2); + assert(std::as_const(v).begin() != sent2); + assert(v.begin() + 4 == sent2); + assert(std::as_const(v).begin() + 4 == sent2); + + // Cannot create a non-const iterator from a const iterator. + static_assert(!std::constructible_from<decltype(sent1), decltype(sent2)>); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, NonSimpleNonCommonConvertibleView{buffer1}); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() != sent1); + assert(v.begin() != sent2); + assert(v.begin() + 4 == sent1); + assert(v.begin() + 4 == sent2); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, NonSimpleNonCommonConvertibleView{buffer1}, std::views::iota(0)); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() != sent1); + assert(v.begin() != sent2); + assert(v.begin() + 4 == sent1); + assert(v.begin() + 4 == sent2); + } + + { + // three ranges + std::ranges::zip_transform_view v( + Tie{}, NonSimpleNonCommonConvertibleView{buffer1}, SimpleCommon{buffer1}, std::ranges::single_view(2.)); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() != sent1); + assert(v.begin() != sent2); + assert(v.begin() + 1 == sent1); + assert(v.begin() + 1 == sent2); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, NonSimpleNonCommonConvertibleView(nullptr, 0)); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() == sent1); + assert(v.begin() == sent2); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), NonSimpleNonCommonConvertibleView{buffer1}, SimpleCommon{buffer1}); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() == sent1); + assert(v.begin() == sent2); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, std::ranges::empty_view<int>(), NonSimpleNonCommonConvertibleView{buffer1}); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() == sent1); + assert(v.begin() == sent2); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, NonSimpleNonCommonConvertibleView{buffer1}, std::ranges::empty_view<int>()); + auto sent1 = v.end(); + std::ranges::sentinel_t<const decltype(v)> sent2 = sent1; + static_assert(!std::is_same_v<decltype(sent1), decltype(sent2)>); + assert(v.begin() == sent1); + assert(v.begin() == sent2); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/eq.pass.cpp new file mode 100644 index 0000000..9b20dac --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/eq.pass.cpp @@ -0,0 +1,199 @@ +//===----------------------------------------------------------------------===// +// +// 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<bool OtherConst> +// requires sentinel_for<zentinel<Const>, ziperator<OtherConst>> +// friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); + +#include <cassert> +#include <compare> +#include <ranges> + +#include "../types.h" + +using Iterator = random_access_iterator<int*>; +using ConstIterator = random_access_iterator<const int*>; + +template <bool Const> +struct ComparableSentinel { + using Iter = std::conditional_t<Const, ConstIterator, Iterator>; + Iter iter_; + + explicit ComparableSentinel() = default; + constexpr explicit ComparableSentinel(const Iter& it) : iter_(it) {} + + constexpr friend bool operator==(const Iterator& i, const ComparableSentinel& s) { return base(i) == base(s.iter_); } + + constexpr friend bool operator==(const ConstIterator& i, const ComparableSentinel& s) { + return base(i) == base(s.iter_); + } +}; + +struct ComparableView : IntBufferView { + using IntBufferView::IntBufferView; + + constexpr auto begin() { return Iterator(buffer_); } + constexpr auto begin() const { return ConstIterator(buffer_); } + constexpr auto end() { return ComparableSentinel<false>(Iterator(buffer_ + size_)); } + constexpr auto end() const { return ComparableSentinel<true>(ConstIterator(buffer_ + size_)); } +}; + +struct ConstIncompatibleView : std::ranges::view_base { + cpp17_input_iterator<int*> begin(); + forward_iterator<const int*> begin() const; + sentinel_wrapper<cpp17_input_iterator<int*>> end(); + sentinel_wrapper<forward_iterator<const int*>> end() const; +}; + +template <class Iter, class Sent> +concept EqualComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&>; + +constexpr bool test() { + int buffer1[4] = {1, 2, 3, 4}; + int buffer2[5] = {1, 2, 3, 4, 5}; + int buffer3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + { + // const and non-const have different iterator/sentinel types + std::ranges::zip_transform_view v{ + MakeTuple{}, NonSimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)}; + using ZipTransformView = decltype(v); + static_assert(!std::ranges::common_range<ZipTransformView>); + static_assert(!simple_view<ZipTransformView>); + + assert(v.begin() != v.end()); + assert(v.begin() + 4 == v.end()); + + // const_iterator (const int*) converted to iterator (int*) + assert(v.begin() + 4 == std::as_const(v).end()); + + using Iter = std::ranges::iterator_t<decltype(v)>; + using ConstIter = std::ranges::iterator_t<const decltype(v)>; + static_assert(!std::is_same_v<Iter, ConstIter>); + using Sentinel = std::ranges::sentinel_t<decltype(v)>; + using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; + static_assert(!std::is_same_v<Sentinel, ConstSentinel>); + + static_assert(EqualComparable<Iter, Sentinel>); + static_assert(!EqualComparable<ConstIter, Sentinel>); + static_assert(EqualComparable<Iter, ConstSentinel>); + static_assert(EqualComparable<ConstIter, ConstSentinel>); + } + + { + // underlying const/non-const sentinel can be compared with both const/non-const iterator + std::ranges::zip_transform_view v{MakeTuple{}, ComparableView(buffer1), ComparableView(buffer2)}; + using ZipTransformView = decltype(v); + static_assert(!std::ranges::common_range<ZipTransformView>); + static_assert(!simple_view<ZipTransformView>); + + assert(v.begin() != v.end()); + assert(v.begin() + 4 == v.end()); + assert(std::as_const(v).begin() + 4 == v.end()); + assert(std::as_const(v).begin() + 4 == std::as_const(v).end()); + assert(v.begin() + 4 == std::as_const(v).end()); + + using Iter = std::ranges::iterator_t<decltype(v)>; + using ConstIter = std::ranges::iterator_t<const decltype(v)>; + static_assert(!std::is_same_v<Iter, ConstIter>); + using Sentinel = std::ranges::sentinel_t<decltype(v)>; + using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; + static_assert(!std::is_same_v<Sentinel, ConstSentinel>); + + static_assert(EqualComparable<Iter, Sentinel>); + static_assert(EqualComparable<ConstIter, Sentinel>); + static_assert(EqualComparable<Iter, ConstSentinel>); + static_assert(EqualComparable<ConstIter, ConstSentinel>); + } + + { + // underlying const/non-const sentinel cannot be compared with non-const/const iterator + std::ranges::zip_transform_view v{MakeTuple{}, ComparableView(buffer1), ConstIncompatibleView{}}; + using ZipTransformView = decltype(v); + static_assert(!std::ranges::common_range<ZipTransformView>); + static_assert(!simple_view<ZipTransformView>); + + using Iter = std::ranges::iterator_t<decltype(v)>; + using ConstIter = std::ranges::iterator_t<const decltype(v)>; + static_assert(!std::is_same_v<Iter, ConstIter>); + using Sentinel = std::ranges::sentinel_t<decltype(v)>; + using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; + static_assert(!std::is_same_v<Sentinel, ConstSentinel>); + + static_assert(EqualComparable<Iter, Sentinel>); + static_assert(!EqualComparable<ConstIter, Sentinel>); + static_assert(!EqualComparable<Iter, ConstSentinel>); + static_assert(EqualComparable<ConstIter, ConstSentinel>); + } + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, ComparableView{buffer1}); + assert(v.begin() != v.end()); + assert(v.begin() + 4 == v.end()); + assert(v.begin() + 4 == std::as_const(v).end()); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, ComparableView{buffer2}, std::views::iota(0)); + assert(v.begin() != v.end()); + assert(v.begin() + 5 == v.end()); + assert(v.begin() + 5 == std::as_const(v).end()); + } + + { + // three ranges + std::ranges::zip_transform_view v( + Tie{}, ComparableView{buffer1}, SimpleNonCommon{buffer2}, std::ranges::single_view(2.)); + assert(v.begin() != v.end()); + assert(v.begin() + 1 == v.end()); + assert(v.begin() + 1 == std::as_const(v).end()); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, ComparableView(nullptr, 0)); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), ComparableView{buffer1}, SimpleCommon{buffer2}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, std::ranges::empty_view<int>(), ComparableView{buffer2}); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, ComparableView{buffer2}, std::ranges::empty_view<int>()); + assert(v.begin() == v.end()); + assert(std::as_const(v).begin() == std::as_const(v).end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/minus.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/minus.pass.cpp new file mode 100644 index 0000000..fc29a00 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/sentinel/minus.pass.cpp @@ -0,0 +1,279 @@ +//===----------------------------------------------------------------------===// +// +// 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<bool OtherConst> +// requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>> +// friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> +// operator-(const sentinel& x, const iterator<OtherConst>& y); + +#include <cassert> +#include <concepts> +#include <functional> +#include <ranges> +#include <tuple> + +#include "../types.h" + +template <class Base = int*> +struct convertible_forward_sized_iterator { + Base it_ = nullptr; + + using iterator_category = std::forward_iterator_tag; + using value_type = int; + using difference_type = std::intptr_t; + + convertible_forward_sized_iterator() = default; + constexpr convertible_forward_sized_iterator(Base it) : it_(it) {} + + template <std::convertible_to<Base> U> + constexpr convertible_forward_sized_iterator(const convertible_forward_sized_iterator<U>& it) : it_(it.it_) {} + + constexpr decltype(*Base{}) operator*() const { return *it_; } + + constexpr convertible_forward_sized_iterator& operator++() { + ++it_; + return *this; + } + constexpr convertible_forward_sized_iterator operator++(int) { return forward_sized_iterator(it_++); } + + friend constexpr bool + operator==(const convertible_forward_sized_iterator&, const convertible_forward_sized_iterator&) = default; + + friend constexpr difference_type + operator-(const convertible_forward_sized_iterator& x, const convertible_forward_sized_iterator& y) { + return x.it_ - y.it_; + } +}; +static_assert(std::forward_iterator<convertible_forward_sized_iterator<>>); + +template <class Base> +struct convertible_sized_sentinel { + Base base_; + explicit convertible_sized_sentinel() = default; + constexpr convertible_sized_sentinel(const Base& it) : base_(it) {} + + template <std::convertible_to<Base> U> + constexpr convertible_sized_sentinel(const convertible_sized_sentinel<U>& other) : base_(other.base_) {} + + template <class U> + requires(std::convertible_to<Base, U> || std::convertible_to<U, Base>) + friend constexpr bool operator==(const convertible_sized_sentinel& s, const U& base) { + return s.base_ == base; + } + template <class U> + requires(std::convertible_to<Base, U> || std::convertible_to<U, Base>) + friend constexpr auto operator-(const convertible_sized_sentinel& s, const U& i) { + return s.base_ - i; + } + + template <class U> + requires(std::convertible_to<Base, U> || std::convertible_to<U, Base>) + friend constexpr auto operator-(const U& i, const convertible_sized_sentinel& s) { + return i - s.base_; + } +}; +static_assert(std::sized_sentinel_for<convertible_sized_sentinel<convertible_forward_sized_iterator<>>, + convertible_forward_sized_iterator<>>); +static_assert(std::sized_sentinel_for<convertible_sized_sentinel<convertible_forward_sized_iterator<const int*>>, + convertible_forward_sized_iterator<int*>>); +static_assert(std::sized_sentinel_for<convertible_sized_sentinel<convertible_forward_sized_iterator<int*>>, + convertible_forward_sized_iterator<const int*>>); + +struct ConstCompatibleForwardSized : IntBufferView { + using IntBufferView::IntBufferView; + + using iterator = convertible_forward_sized_iterator<int*>; + using const_iterator = convertible_forward_sized_iterator<const int*>; + + constexpr iterator begin() { return {buffer_}; } + constexpr const_iterator begin() const { return {buffer_}; } + constexpr convertible_sized_sentinel<iterator> end() { return iterator{buffer_ + size_}; } + constexpr convertible_sized_sentinel<const_iterator> end() const { return const_iterator{buffer_ + size_}; } +}; + +template <class T, class U> +concept HasMinus = std::invocable<std::minus<>, const T&, const U&>; + +template <class T> +concept SentinelHasMinus = HasMinus<std::ranges::sentinel_t<T>, std::ranges::iterator_t<T>>; + +constexpr bool test() { + int buffer1[5] = {1, 2, 3, 4, 5}; + int buffer2[3] = {1, 2, 3}; + + { + // shortest range + std::ranges::zip_transform_view v(MakeTuple{}, std::views::iota(0, 3), ForwardSizedNonCommon(buffer1)); + static_assert(!std::ranges::common_range<decltype(v)>); + auto it = v.begin(); + auto st = v.end(); + assert(st - it == 3); + assert(st - std::ranges::next(it, 1) == 2); + + assert(it - st == -3); + assert(std::ranges::next(it, 1) - st == -2); + static_assert(SentinelHasMinus<decltype(v)>); + } + + { + // underlying sentinel does not model sized_sentinel_for + std::ranges::zip_transform_view v(MakeTuple{}, std::views::iota(0), SizedRandomAccessView(buffer1)); + static_assert(!std::ranges::common_range<decltype(v)>); + static_assert(!SentinelHasMinus<decltype(v)>); + } + + { + // const incompatible: + // underlying const sentinels cannot subtract underlying iterators + // underlying sentinels cannot subtract underlying const iterators + std::ranges::zip_transform_view v(MakeTuple{}, NonSimpleForwardSizedNonCommon{buffer1}); + static_assert(!std::ranges::common_range<decltype(v)>); + static_assert(!simple_view<decltype(v)>); + + using Iter = std::ranges::iterator_t<decltype(v)>; + using ConstIter = std::ranges::iterator_t<const decltype(v)>; + static_assert(!std::is_same_v<Iter, ConstIter>); + using Sentinel = std::ranges::sentinel_t<decltype(v)>; + using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; + static_assert(!std::is_same_v<Sentinel, ConstSentinel>); + + static_assert(HasMinus<Iter, Sentinel>); + static_assert(HasMinus<Sentinel, Iter>); + static_assert(HasMinus<ConstIter, ConstSentinel>); + static_assert(HasMinus<ConstSentinel, ConstIter>); + auto it = v.begin(); + auto const_it = std::as_const(v).begin(); + auto st = v.end(); + auto const_st = std::as_const(v).end(); + assert(it - st == -5); + assert(st - it == 5); + assert(const_it - const_st == -5); + assert(const_st - const_it == 5); + + static_assert(!HasMinus<Iter, ConstSentinel>); + static_assert(!HasMinus<ConstSentinel, Iter>); + static_assert(!HasMinus<ConstIter, Sentinel>); + static_assert(!HasMinus<Sentinel, ConstIter>); + } + + { + // const compatible allow non-const to const conversion + std::ranges::zip_transform_view v(MakeTuple{}, ConstCompatibleForwardSized{buffer1}); + static_assert(!std::ranges::common_range<decltype(v)>); + static_assert(!simple_view<decltype(v)>); + + using Iter = std::ranges::iterator_t<decltype(v)>; + using ConstIter = std::ranges::iterator_t<const decltype(v)>; + static_assert(!std::is_same_v<Iter, ConstIter>); + using Sentinel = std::ranges::sentinel_t<decltype(v)>; + using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; + static_assert(!std::is_same_v<Sentinel, ConstSentinel>); + + static_assert(HasMinus<Iter, Sentinel>); + static_assert(HasMinus<Sentinel, Iter>); + static_assert(HasMinus<ConstIter, ConstSentinel>); + static_assert(HasMinus<ConstSentinel, ConstIter>); + static_assert(HasMinus<Iter, ConstSentinel>); + static_assert(HasMinus<ConstSentinel, Iter>); + static_assert(HasMinus<ConstIter, Sentinel>); + static_assert(HasMinus<Sentinel, ConstIter>); + + auto it = v.begin(); + auto const_it = std::as_const(v).begin(); + auto st = v.end(); + auto const_st = std::as_const(v).end(); + + assert(it - st == -5); + assert(st - it == 5); + assert(const_it - const_st == -5); + assert(const_st - const_it == 5); + assert(it - const_st == -5); + assert(const_st - it == 5); + assert(const_it - st == -5); + assert(st - const_it == 5); + } + + auto testMinus = [](auto&& v, auto distance) { + auto it = v.begin(); + auto const_it = std::as_const(v).begin(); + auto st = v.end(); + auto const_st = std::as_const(v).end(); + + assert(it - st == -distance); + assert(st - it == distance); + assert(const_it - const_st == -distance); + assert(const_st - const_it == distance); + assert(it - const_st == -distance); + assert(const_st - it == distance); + assert(const_it - st == -distance); + assert(st - const_it == distance); + }; + + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, ConstCompatibleForwardSized{buffer1}); + testMinus(v, 5); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, ConstCompatibleForwardSized{buffer1}, std::views::iota(0, 100)); + testMinus(v, 5); + } + + { + // three ranges + std::ranges::zip_transform_view v( + Tie{}, + ConstCompatibleForwardSized{buffer1}, + ConstCompatibleForwardSized{buffer2}, + std::ranges::single_view(2.)); + testMinus(v, 1); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, ConstCompatibleForwardSized(nullptr, 0)); + testMinus(v, 0); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), ConstCompatibleForwardSized{buffer1}, SimpleCommon{buffer2}); + testMinus(v, 0); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, + ConstCompatibleForwardSized{buffer1}, + std::ranges::empty_view<int>(), + ConstCompatibleForwardSized{buffer2}); + testMinus(v, 0); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer1}, ConstCompatibleForwardSized{buffer2}, std::ranges::empty_view<int>()); + testMinus(v, 0); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/size.pass.cpp new file mode 100644 index 0000000..140bdc3 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/size.pass.cpp @@ -0,0 +1,128 @@ +//===----------------------------------------------------------------------===// +// +// 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() requires sized_range<InnerView> +// constexpr auto size() const requires sized_range<const InnerView> + +#include <ranges> + +#include <cassert> + +#include "test_iterators.h" +#include "types.h" + +int buffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; +struct SizedView : std::ranges::view_base { + std::size_t size_ = 0; + constexpr SizedView(std::size_t s) : size_(s) {} + constexpr auto begin() const { return buffer; } + constexpr auto end() const { return buffer + size_; } +}; + +struct SizedNonConst : std::ranges::view_base { + using iterator = forward_iterator<int*>; + std::size_t size_ = 0; + constexpr SizedNonConst(std::size_t s) : size_(s) {} + constexpr auto begin() const { return iterator{buffer}; } + constexpr auto end() const { return iterator{buffer + size_}; } + constexpr std::size_t size() { return size_; } +}; + +struct ConstNonConstDifferentSize : std::ranges::view_base { + constexpr auto begin() const { return buffer; } + constexpr auto end() const { return buffer + 8; } + + constexpr auto size() { return 5; } + constexpr auto size() const { return 6; } +}; + +constexpr bool test() { + { + // one range + std::ranges::zip_transform_view v(MakeTuple{}, SimpleCommon{buffer}); + assert(v.size() == 9); + assert(std::as_const(v).size() == 9); + } + + { + // two ranges + std::ranges::zip_transform_view v(GetFirst{}, SimpleCommon{buffer}, SizedView(3)); + assert(v.size() == 3); + assert(std::as_const(v).size() == 3); + } + + { + // three ranges + std::ranges::zip_transform_view v(Tie{}, SimpleCommon{buffer}, SizedView{6}, std::ranges::single_view(2.)); + assert(v.size() == 1); + assert(std::as_const(v).size() == 1); + } + + { + // single empty range + std::ranges::zip_transform_view v(MakeTuple{}, std::ranges::empty_view<int>()); + assert(v.size() == 0); + assert(std::as_const(v).size() == 0); + } + + { + // empty range at the beginning + std::ranges::zip_transform_view v( + MakeTuple{}, std::ranges::empty_view<int>(), SimpleCommon{buffer}, SimpleCommon{buffer}); + assert(v.size() == 0); + assert(std::as_const(v).size() == 0); + } + + { + // empty range in the middle + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, std::ranges::empty_view<int>(), SimpleCommon{buffer}); + assert(v.size() == 0); + assert(std::as_const(v).size() == 0); + } + + { + // empty range at the end + std::ranges::zip_transform_view v( + MakeTuple{}, SimpleCommon{buffer}, SimpleCommon{buffer}, std::ranges::empty_view<int>()); + assert(v.size() == 0); + assert(std::as_const(v).size() == 0); + } + + { + // const-view non-sized range + std::ranges::zip_transform_view v(MakeTuple{}, SizedNonConst(2), SizedView(3)); + assert(v.size() == 2); + static_assert(std::ranges::sized_range<decltype(v)>); + static_assert(!std::ranges::sized_range<decltype(std::as_const(v))>); + } + + { + // const/non-const has different sizes + std::ranges::zip_transform_view v(MakeTuple{}, ConstNonConstDifferentSize{}); + assert(v.size() == 5); + assert(std::as_const(v).size() == 6); + } + + { + // underlying range not sized + std::ranges::zip_transform_view v(MakeTuple{}, InputCommonView{buffer}); + static_assert(!std::ranges::sized_range<decltype(v)>); + static_assert(!std::ranges::sized_range<decltype(std::as_const(v))>); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip.transform/types.h b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/types.h new file mode 100644 index 0000000..dc6a40a --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip.transform/types.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TRANSFORM_TYPES_H +#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TRANSFORM_TYPES_H + +#include <functional> +#include <ranges> + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_range.h" +#include "../range_adaptor_types.h" + +#if TEST_STD_VER <= 20 +# error "range.zip.transform/types.h" can only be included in builds supporting C++20 +#endif + +struct IntView : std::ranges::view_base { + int* begin() const; + int* end() const; +}; + +struct MakeTuple { + constexpr auto operator()(auto&&... args) const { return std::tuple(std::forward<decltype(args)>(args)...); } +}; + +struct Tie { + constexpr auto operator()(auto&&... args) const { return std::tie(std::forward<decltype(args)>(args)...); } +}; + +struct GetFirst { + constexpr decltype(auto) operator()(auto&& first, auto&&...) const { return std::forward<decltype(first)>(first); } +}; + +struct NoConstBeginView : std::ranges::view_base { + int* begin(); + int* end(); +}; + +struct ConstNonConstDifferentView : std::ranges::view_base { + int* begin(); + const int* begin() const; + int* end(); + const int* end() const; +}; + +struct NonConstOnlyFn { + int operator()(int&) const; + int operator()(const int&) const = delete; +}; + +#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TRANSFORM_TYPES_H diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp index 637d776..837ed9e 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp @@ -18,7 +18,7 @@ #include <tuple> #include <utility> -#include "types.h" +#include "../range_adaptor_types.h" template <class T> concept HasConstBegin = requires(const T& ct) { ct.begin(); }; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp index bdfd58ff..34c81f0 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp @@ -18,7 +18,7 @@ #include <type_traits> #include <utility> -#include "types.h" +#include "../range_adaptor_types.h" static_assert(std::is_invocable_v<decltype((std::views::zip))>); static_assert(!std::is_invocable_v<decltype((std::views::zip)), int>); diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.views.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.views.pass.cpp index b4a16de..513d268 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.views.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.views.pass.cpp @@ -13,7 +13,7 @@ #include <ranges> #include <tuple> -#include "types.h" +#include "../range_adaptor_types.h" template <class T> void conversion_test(T); diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/end.pass.cpp index b7f6447..7cf9f5f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/end.pass.cpp @@ -14,7 +14,7 @@ #include <ranges> #include <tuple> -#include "types.h" +#include "../range_adaptor_types.h" // ID | simple | common | bidi | random | sized | #views | v.end() | as_const(v) // | | | | access | | | | .end() diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/arithmetic.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/arithmetic.pass.cpp index efe64b3..444f3ed 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/arithmetic.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/arithmetic.pass.cpp @@ -25,7 +25,7 @@ #include <concepts> #include <functional> -#include "../types.h" +#include "../../range_adaptor_types.h" template <class T, class U> concept canPlusEqual = requires(T& t, U& u) { t += u; }; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/compare.pass.cpp index 8ab7346..5ad054c 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/compare.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/compare.pass.cpp @@ -19,7 +19,7 @@ #include "test_iterators.h" #include "test_range.h" -#include "../types.h" +#include "../../range_adaptor_types.h" // This is for testing that zip iterator never calls underlying iterator's >, >=, <=, !=. // The spec indicates that zip iterator's >= is negating zip iterator's < instead of calling underlying iterator's >=. diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.default.pass.cpp index 98078b2..abced16 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.default.pass.cpp @@ -13,7 +13,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" struct PODIter { int i; // deliberately uninitialised diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.other.pass.cpp index 7f9784e..6b8b55f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.other.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/ctor.other.pass.cpp @@ -17,7 +17,7 @@ #include <cassert> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" using ConstIterIncompatibleView = BasicView<forward_iterator<int*>, forward_iterator<int*>, random_access_iterator<const int*>, random_access_iterator<const int*>>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/decrement.pass.cpp index a8422ec..db5a651 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/decrement.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/decrement.pass.cpp @@ -16,7 +16,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" template <class Iter> concept canDecrement = requires(Iter it) { --it; } || requires(Iter it) { it--; }; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/deref.pass.cpp index fb58aa2..61495fa 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/deref.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/deref.pass.cpp @@ -15,7 +15,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" constexpr bool test() { std::array a{1, 2, 3, 4}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/increment.pass.cpp index 94d2bd4..d094779 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/increment.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/increment.pass.cpp @@ -17,7 +17,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" struct InputRange : IntBufferView { using IntBufferView::IntBufferView; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_move.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_move.pass.cpp index 2926b22..f258809 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_move.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_move.pass.cpp @@ -16,7 +16,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" struct ThrowingMove { ThrowingMove() = default; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_swap.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_swap.pass.cpp index bb0ec1c..b12877c 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_swap.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_swap.pass.cpp @@ -15,7 +15,7 @@ #include <cassert> #include <ranges> -#include "../types.h" +#include "../../range_adaptor_types.h" struct ThrowingMove { ThrowingMove() = default; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/member_types.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/member_types.compile.pass.cpp index 2f2f0fc..852ea9b 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/member_types.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/member_types.compile.pass.cpp @@ -16,7 +16,7 @@ #include "test_iterators.h" -#include "../types.h" +#include "../../range_adaptor_types.h" template <class T> struct ForwardView : std::ranges::view_base { diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/singular.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/singular.pass.cpp index 0f7e4c4..5cd76e0 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/singular.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/singular.pass.cpp @@ -16,7 +16,7 @@ #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" struct ThrowOnIncrementIterator { int* it_; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/subscript.pass.cpp index ba3abfa2..deeeebf 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/subscript.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/iterator/subscript.pass.cpp @@ -14,7 +14,7 @@ #include <ranges> #include <cassert> -#include "../types.h" +#include "../../range_adaptor_types.h" constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/range.concept.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/range.concept.compile.pass.cpp index c74c156..4b8587f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/range.concept.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/range.concept.compile.pass.cpp @@ -18,7 +18,7 @@ #include <tuple> #include <utility> -#include "types.h" +#include "../range_adaptor_types.h" void testConceptPair() { int buffer1[2] = {1, 2}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.other.pass.cpp index 11ad73c..c3f50b0 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.other.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.other.pass.cpp @@ -13,7 +13,7 @@ #include <cassert> #include <ranges> -#include "../types.h" +#include "../../range_adaptor_types.h" template <class T> struct convertible_sentinel_wrapper { diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.pass.cpp index 04542c3..fa26d98 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.pass.cpp @@ -17,7 +17,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" #include "test_range.h" using Iterator = random_access_iterator<int*>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/minus.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/minus.pass.cpp index be0a7ba..bcfa340 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/minus.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/minus.pass.cpp @@ -26,7 +26,7 @@ #include <ranges> #include <tuple> -#include "../types.h" +#include "../../range_adaptor_types.h" template <class Base = int*> struct convertible_forward_sized_iterator { diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/size.pass.cpp index 194b3bd..0c0014c 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/size.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/size.pass.cpp @@ -18,7 +18,7 @@ #include <utility> #include "test_iterators.h" -#include "types.h" +#include "../range_adaptor_types.h" int buffer[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; struct View : std::ranges::view_base { diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/types.h b/libcxx/test/std/ranges/range.adaptors/range_adaptor_types.h index e084dcf..288a78ac 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range_adaptor_types.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TYPES_H -#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TYPES_H +#ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ADAPTOR_TYPES_H +#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ADAPTOR_TYPES_H #include <functional> #include <ranges> @@ -17,7 +17,7 @@ #include "test_range.h" #if TEST_STD_VER <= 20 -# error "range.zip/types.h" can only be included in builds supporting C++20 +# error "range.adaptor/types.h" can only be included in builds supporting C++20 #endif // TEST_STD_VER <= 20 template <class T> @@ -27,12 +27,14 @@ struct BufferView : std::ranges::view_base { template <std::size_t N> constexpr BufferView(T (&b)[N]) : buffer_(b), size_(N) {} + + constexpr BufferView(T* b, std::size_t s) : buffer_(b), size_(s) {} }; using IntBufferView = BufferView<int>; template <bool Simple> -struct Common : IntBufferView { +struct Common : IntBufferView { using IntBufferView::IntBufferView; constexpr int* begin() @@ -48,10 +50,10 @@ struct Common : IntBufferView { } constexpr const int* end() const { return buffer_ + size_; } }; -using SimpleCommon = Common<true>; +using SimpleCommon = Common<true>; using NonSimpleCommon = Common<false>; -using SimpleCommonRandomAccessSized = SimpleCommon; +using SimpleCommonRandomAccessSized = SimpleCommon; using NonSimpleCommonRandomAccessSized = NonSimpleCommon; static_assert(std::ranges::common_range<Common<true>>); @@ -64,20 +66,22 @@ template <bool Simple> struct CommonNonRandom : IntBufferView { using IntBufferView::IntBufferView; using const_iterator = forward_iterator<const int*>; - using iterator = forward_iterator<int*>; + using iterator = forward_iterator<int*>; constexpr iterator begin() - requires(!Simple) { + requires(!Simple) + { return iterator(buffer_); } constexpr const_iterator begin() const { return const_iterator(buffer_); } constexpr iterator end() - requires(!Simple) { + requires(!Simple) + { return iterator(buffer_ + size_); } constexpr const_iterator end() const { return const_iterator(buffer_ + size_); } }; -using SimpleCommonNonRandom = CommonNonRandom<true>; +using SimpleCommonNonRandom = CommonNonRandom<true>; using NonSimpleCommonNonRandom = CommonNonRandom<false>; static_assert(std::ranges::common_range<SimpleCommonNonRandom>); @@ -90,18 +94,20 @@ template <bool Simple> struct NonCommon : IntBufferView { using IntBufferView::IntBufferView; constexpr int* begin() - requires(!Simple) { + requires(!Simple) + { return buffer_; } constexpr const int* begin() const { return buffer_; } constexpr sentinel_wrapper<int*> end() - requires(!Simple) { + requires(!Simple) + { return sentinel_wrapper<int*>(buffer_ + size_); } constexpr sentinel_wrapper<const int*> end() const { return sentinel_wrapper<const int*>(buffer_ + size_); } }; -using SimpleNonCommon = NonCommon<true>; +using SimpleNonCommon = NonCommon<true>; using NonSimpleNonCommon = NonCommon<false>; static_assert(!std::ranges::common_range<SimpleNonCommon>); @@ -114,21 +120,23 @@ template <bool Simple> struct NonCommonSized : IntBufferView { using IntBufferView::IntBufferView; constexpr int* begin() - requires(!Simple) { + requires(!Simple) + { return buffer_; } constexpr const int* begin() const { return buffer_; } constexpr sentinel_wrapper<int*> end() - requires(!Simple) { + requires(!Simple) + { return sentinel_wrapper<int*>(buffer_ + size_); } constexpr sentinel_wrapper<const int*> end() const { return sentinel_wrapper<const int*>(buffer_ + size_); } constexpr std::size_t size() const { return size_; } }; -using SimpleNonCommonSized = NonCommonSized<true>; +using SimpleNonCommonSized = NonCommonSized<true>; using SimpleNonCommonRandomAccessSized = SimpleNonCommonSized; -using NonSimpleNonCommonSized = NonCommonSized<false>; +using NonSimpleNonCommonSized = NonCommonSized<false>; using NonSimpleNonCommonRandomAccessSized = NonSimpleNonCommonSized; static_assert(!std::ranges::common_range<SimpleNonCommonSized>); @@ -142,15 +150,17 @@ struct NonCommonNonRandom : IntBufferView { using IntBufferView::IntBufferView; using const_iterator = forward_iterator<const int*>; - using iterator = forward_iterator<int*>; + using iterator = forward_iterator<int*>; constexpr iterator begin() - requires(!Simple) { + requires(!Simple) + { return iterator(buffer_); } constexpr const_iterator begin() const { return const_iterator(buffer_); } constexpr sentinel_wrapper<iterator> end() - requires(!Simple) { + requires(!Simple) + { return sentinel_wrapper<iterator>(iterator(buffer_ + size_)); } constexpr sentinel_wrapper<const_iterator> end() const { @@ -158,7 +168,7 @@ struct NonCommonNonRandom : IntBufferView { } }; -using SimpleNonCommonNonRandom = NonCommonNonRandom<true>; +using SimpleNonCommonNonRandom = NonCommonNonRandom<true>; using NonSimpleNonCommonNonRandom = NonCommonNonRandom<false>; static_assert(!std::ranges::common_range<SimpleNonCommonNonRandom>); @@ -172,13 +182,15 @@ struct BasicView : IntBufferView { using IntBufferView::IntBufferView; constexpr NonConstIter begin() - requires(!std::is_same_v<Iter, NonConstIter>) { + requires(!std::is_same_v<Iter, NonConstIter>) + { return NonConstIter(buffer_); } constexpr Iter begin() const { return Iter(buffer_); } constexpr NonConstSent end() - requires(!std::is_same_v<Sent, NonConstSent>) { + requires(!std::is_same_v<Sent, NonConstSent>) + { if constexpr (std::is_same_v<NonConstIter, NonConstSent>) { return NonConstIter(buffer_ + size_); } else { @@ -200,10 +212,10 @@ struct forward_sized_iterator { Base it_ = nullptr; using iterator_category = std::forward_iterator_tag; - using value_type = int; - using difference_type = std::intptr_t; - using pointer = Base; - using reference = decltype(*Base{}); + using value_type = int; + using difference_type = std::intptr_t; + using pointer = Base; + using reference = decltype(*Base{}); forward_sized_iterator() = default; constexpr forward_sized_iterator(Base it) : it_(it) {} @@ -232,8 +244,11 @@ static_assert(std::ranges::common_range<ForwardSizedView>); static_assert(!std::ranges::random_access_range<ForwardSizedView>); static_assert(simple_view<ForwardSizedView>); -using NonSimpleForwardSizedView = BasicView<forward_sized_iterator<const int*>, forward_sized_iterator<const int*>, - forward_sized_iterator<int*>, forward_sized_iterator<int*>>; +using NonSimpleForwardSizedView = + BasicView<forward_sized_iterator<const int*>, + forward_sized_iterator<const int*>, + forward_sized_iterator<int*>, + forward_sized_iterator<int*>>; static_assert(std::ranges::forward_range<NonSimpleForwardSizedView>); static_assert(std::ranges::sized_range<NonSimpleForwardSizedView>); static_assert(std::ranges::common_range<NonSimpleForwardSizedView>); @@ -248,8 +263,10 @@ static_assert(!std::ranges::random_access_range<ForwardSizedNonCommon>); static_assert(simple_view<ForwardSizedNonCommon>); using NonSimpleForwardSizedNonCommon = - BasicView<forward_sized_iterator<const int*>, sized_sentinel<forward_sized_iterator<const int*>>, - forward_sized_iterator<int*>, sized_sentinel<forward_sized_iterator<int*>>>; + BasicView<forward_sized_iterator<const int*>, + sized_sentinel<forward_sized_iterator<const int*>>, + forward_sized_iterator<int*>, + sized_sentinel<forward_sized_iterator<int*>>>; static_assert(std::ranges::forward_range<NonSimpleForwardSizedNonCommon>); static_assert(std::ranges::sized_range<NonSimpleForwardSizedNonCommon>); static_assert(!std::ranges::common_range<NonSimpleForwardSizedNonCommon>); @@ -278,8 +295,10 @@ static_assert(!std::ranges::sized_range<NonSizedRandomAccessView>); static_assert(simple_view<NonSizedRandomAccessView>); using NonSimpleNonSizedRandomAccessView = - BasicView<random_access_iterator<const int*>, sentinel_wrapper<random_access_iterator<const int*>>, - random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>> >; + BasicView<random_access_iterator<const int*>, + sentinel_wrapper<random_access_iterator<const int*>>, + random_access_iterator<int*>, + sentinel_wrapper<random_access_iterator<int*>> >; static_assert(!std::ranges::contiguous_range<NonSimpleNonSizedRandomAccessView>); static_assert(std::ranges::random_access_range<NonSimpleNonSizedRandomAccessView>); static_assert(!std::ranges::common_range<NonSimpleNonSizedRandomAccessView>); @@ -308,8 +327,11 @@ static_assert(!std::ranges::forward_range<InputCommonView>); static_assert(std::ranges::common_range<InputCommonView>); static_assert(simple_view<InputCommonView>); -using NonSimpleInputCommonView = BasicView<common_input_iterator<const int*>, common_input_iterator<const int*>, - common_input_iterator<int*>, common_input_iterator<int*>>; +using NonSimpleInputCommonView = + BasicView<common_input_iterator<const int*>, + common_input_iterator<const int*>, + common_input_iterator<int*>, + common_input_iterator<int*>>; static_assert(std::ranges::input_range<NonSimpleInputCommonView>); static_assert(!std::ranges::forward_range<NonSimpleInputCommonView>); static_assert(std::ranges::common_range<NonSimpleInputCommonView>); @@ -322,8 +344,10 @@ static_assert(!std::ranges::common_range<InputNonCommonView>); static_assert(simple_view<InputNonCommonView>); using NonSimpleInputNonCommonView = - BasicView<common_input_iterator<const int*>, sentinel_wrapper<common_input_iterator<const int*>>, - common_input_iterator<int*>, sentinel_wrapper<common_input_iterator<int*>>>; + BasicView<common_input_iterator<const int*>, + sentinel_wrapper<common_input_iterator<const int*>>, + common_input_iterator<int*>, + sentinel_wrapper<common_input_iterator<int*>>>; static_assert(std::ranges::input_range<InputNonCommonView>); static_assert(!std::ranges::forward_range<InputNonCommonView>); static_assert(!std::ranges::common_range<InputNonCommonView>); @@ -336,8 +360,11 @@ static_assert(!std::ranges::random_access_range<BidiCommonView>); static_assert(std::ranges::common_range<BidiCommonView>); static_assert(simple_view<BidiCommonView>); -using NonSimpleBidiCommonView = BasicView<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, - bidirectional_iterator<int*>, bidirectional_iterator<int*>>; +using NonSimpleBidiCommonView = + BasicView<bidirectional_iterator<const int*>, + bidirectional_iterator<const int*>, + bidirectional_iterator<int*>, + bidirectional_iterator<int*>>; static_assert(!std::ranges::sized_range<NonSimpleBidiCommonView>); static_assert(std::ranges::bidirectional_range<NonSimpleBidiCommonView>); static_assert(!std::ranges::random_access_range<NonSimpleBidiCommonView>); @@ -372,8 +399,10 @@ static_assert(!std::ranges::common_range<BidiNonCommonView>); static_assert(simple_view<BidiNonCommonView>); using NonSimpleBidiNonCommonView = - BasicView<bidirectional_iterator<const int*>, sentinel_wrapper<bidirectional_iterator<const int*>>, - bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>; + BasicView<bidirectional_iterator<const int*>, + sentinel_wrapper<bidirectional_iterator<const int*>>, + bidirectional_iterator<int*>, + sentinel_wrapper<bidirectional_iterator<int*>>>; static_assert(!std::ranges::sized_range<NonSimpleBidiNonCommonView>); static_assert(std::ranges::bidirectional_range<NonSimpleBidiNonCommonView>); static_assert(!std::ranges::random_access_range<NonSimpleBidiNonCommonView>); @@ -388,24 +417,25 @@ static_assert(!std::ranges::common_range<SizedBidiNonCommonView>); static_assert(simple_view<SizedBidiNonCommonView>); using NonSimpleSizedBidiNonCommonView = - BasicView<bidirectional_iterator<const int*>, sized_sentinel<bidirectional_iterator<const int*>>, - bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>; + BasicView<bidirectional_iterator<const int*>, + sized_sentinel<bidirectional_iterator<const int*>>, + bidirectional_iterator<int*>, + sized_sentinel<bidirectional_iterator<int*>>>; static_assert(std::ranges::sized_range<NonSimpleSizedBidiNonCommonView>); static_assert(std::ranges::bidirectional_range<NonSimpleSizedBidiNonCommonView>); static_assert(!std::ranges::random_access_range<NonSimpleSizedBidiNonCommonView>); static_assert(!std::ranges::common_range<NonSimpleSizedBidiNonCommonView>); static_assert(!simple_view<NonSimpleSizedBidiNonCommonView>); -namespace adltest{ +namespace adltest { struct iter_move_swap_iterator { - std::reference_wrapper<int> iter_move_called_times; std::reference_wrapper<int> iter_swap_called_times; int i = 0; using iterator_category = std::input_iterator_tag; - using value_type = int; - using difference_type = std::intptr_t; + using value_type = int; + using difference_type = std::intptr_t; constexpr int operator*() const { return i; } @@ -435,4 +465,4 @@ struct IterMoveSwapRange { }; } // namespace adltest -#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TYPES_H +#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ADAPTOR_TYPES_H diff --git a/libcxx/test/std/ranges/ranges_robust_against_no_unique_address.pass.cpp b/libcxx/test/std/ranges/ranges_robust_against_no_unique_address.pass.cpp index 3b35271..0618665 100644 --- a/libcxx/test/std/ranges/ranges_robust_against_no_unique_address.pass.cpp +++ b/libcxx/test/std/ranges/ranges_robust_against_no_unique_address.pass.cpp @@ -58,6 +58,7 @@ constexpr bool test() { #if TEST_STD_VER >= 23 testOne<std::ranges::chunk_by_view<View, Pred>>(); testOne<std::ranges::repeat_view<Pred>>(); + testOne<std::ranges::zip_transform_view<Pred, View>>(); #endif return true; } diff --git a/libcxx/test/std/re/re.regex/re.regex.construct/bad_range.pass.cpp b/libcxx/test/std/re/re.regex/re.regex.construct/bad_range.pass.cpp index 023bc0e..ecfdaee 100644 --- a/libcxx/test/std/re/re.regex/re.regex.construct/bad_range.pass.cpp +++ b/libcxx/test/std/re/re.regex/re.regex.construct/bad_range.pass.cpp @@ -14,6 +14,8 @@ // template <class ST, class SA> // basic_regex(const basic_string<charT, ST, SA>& s); +// XFAIL: FROZEN-CXX03-HEADERS-FIXME + #include <regex> #include <cassert> #include "test_macros.h" @@ -33,6 +35,7 @@ int main(int, char**) { assert(error_range_thrown("([\\w-a])")); assert(error_range_thrown("([a-\\w])")); + assert(error_range_thrown("([w-a])")); - return 0; + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/shared_ptr_array.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/shared_ptr_array.pass.cpp index 9ff1482..9bc695c 100644 --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/shared_ptr_array.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/shared_ptr_array.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // These compiler versions and platforms don't enable sized deallocation by default. -// ADDITIONAL_COMPILE_FLAGS(clang-17): -fsized-deallocation -// ADDITIONAL_COMPILE_FLAGS(clang-18): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(apple-clang-16): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=x86_64-w64-windows-gnu): -fsized-deallocation // ADDITIONAL_COMPILE_FLAGS(target=i686-w64-windows-gnu): -fsized-deallocation diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_virtual_base_of.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_virtual_base_of.pass.cpp index 47c95c6..2e0b1e9 100644 --- a/libcxx/test/std/utilities/meta/meta.rel/is_virtual_base_of.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.rel/is_virtual_base_of.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23 // These compilers don't support __builtin_is_virtual_base_of yet. -// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17 +// UNSUPPORTED: clang-19, gcc-14, apple-clang-16, apple-clang-17 // <type_traits> diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp index 192943d..b7fd093 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // These compilers don't support __builtin_is_implicit_lifetime yet. -// UNSUPPORTED: clang-18, clang-19, gcc-14, gcc-15, apple-clang-16, apple-clang-17 +// UNSUPPORTED: clang-19, gcc-14, gcc-15, apple-clang-16, apple-clang-17 // <type_traits> diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp index e5b10f5..1ca9d44 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // These compilers don't support __builtin_is_implicit_lifetime yet. -// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17 +// UNSUPPORTED: clang-19, gcc-14, apple-clang-16, apple-clang-17 // <type_traits> diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp index 03bec8c..ad53c81 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp @@ -9,7 +9,7 @@ // REQUIRES: std-at-least-c++23 // These compilers don't support std::reference_converts_from_temporary yet. -// UNSUPPORTED: android, apple-clang-16, clang-19.1 +// UNSUPPORTED: apple-clang-16, clang-19.1 // <type_traits> diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp index 82688b1..73cc4f3 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp @@ -9,7 +9,7 @@ // REQUIRES: std-at-least-c++23 // These compilers don't support std::reference_converts_from_temporary yet. -// UNSUPPORTED: android, apple-clang-16, clang-18, clang-19.1 +// UNSUPPORTED: apple-clang-16, clang-19.1 // <type_traits> diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 34b79b3..2c14de8 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -214,7 +214,7 @@ static constexpr bool can_make_from_tuple = template <class T, class Tuple> auto test_make_from_tuple_impl(T&&, Tuple&& t) -> decltype(std::__make_from_tuple_impl<T>( - t, typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<Tuple>>>::type{}), + t, typename std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>()), std::uint8_t()) { return 0; } diff --git a/libcxx/utils/synchronize_csv_status_files.py b/libcxx/utils/synchronize_csv_status_files.py index 3132857..5dbd734 100755 --- a/libcxx/utils/synchronize_csv_status_files.py +++ b/libcxx/utils/synchronize_csv_status_files.py @@ -231,7 +231,7 @@ class PaperInfo: return PaperInfo( paper_number=paper, - paper_name=issue['title'], + paper_name=issue['title'].removeprefix(paper + ': '), status=PaperStatus.from_github_issue(issue), meeting=issue.get('meeting Voted', None), first_released_version=None, # TODO @@ -269,14 +269,14 @@ def merge(paper: PaperInfo, gh: PaperInfo) -> PaperInfo: def load_csv(file: pathlib.Path) -> List[Tuple]: rows = [] - with open(file, newline='') as f: + with open(file, newline='', encoding='utf-8') as f: reader = csv.reader(f, delimiter=',') for row in reader: rows.append(row) return rows def write_csv(output: pathlib.Path, rows: List[Tuple]): - with open(output, 'w', newline='') as f: + with open(output, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f, quoting=csv.QUOTE_ALL, lineterminator='\n') for row in rows: writer.writerow(row) @@ -417,7 +417,7 @@ def main(argv): # Load all the Github issues tracking papers from Github. if args.load_github_from: print(f"Loading all issues from {args.load_github_from}") - with open(args.load_github_from, 'r') as f: + with open(args.load_github_from, 'r', encoding='utf-8') as f: project_info = json.load(f) else: print("Loading all issues from Github") |