diff --git a/libcxx/docs/Status/ZipProjects.csv b/libcxx/docs/Status/ZipProjects.csv --- a/libcxx/docs/Status/ZipProjects.csv +++ b/libcxx/docs/Status/ZipProjects.csv @@ -8,9 +8,9 @@ | `[vector.bool] `_, "[vector::reference] add const operator= overload", None, Nikolas Klauser, |Not Started| | `[iterator.concept.winc] `_, "Update weakly_comparable", None, Unassigned, |Not Started| | `[range.zip] `_, "zip_view", "| `zip_view::iterator` -| `zip_view::sentinel`", Unassigned, |Not Started| -| `[range.zip.iterator] `_, "zip_view::iterator", None, Unassigned, |Not Started| -| `[range.zip.sentinel] `_, "zip_view::sentinel", None, Unassigned, |Not Started| +| `zip_view::sentinel`", Hui Xie, |Complete| +| `[range.zip.iterator] `_, "zip_view::iterator", None, Hui Xie, |Complete| +| `[range.zip.sentinel] `_, "zip_view::sentinel", None, Hui Xie, |Complete| | `[range.zip.transform.view] `_, "zip_transform_view", "| `zip_transform_view::iterator` | `zip_transform_view::sentinel`", Unassigned, |Not Started| | `[range.zip.transform.iterator] `_, "zip_transform_view::iterator", None, Unassigned, |Not Started| diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -11,181 +11,197 @@ #include <__config> -#include <__algorithm/min.h> +#include <__algorithm/ranges_min.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/equality_comparable.h> #include <__functional/invoke.h> +#include <__functional/operations.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> #include <__ranges/access.h> #include <__ranges/all.h> -#include <__ranges/empty_view.h> #include <__ranges/concepts.h> +#include <__ranges/empty_view.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple> +#include <__utility/forward.h> +#include <__utility/integer_sequence.h> +#include <__utility/move.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -#pragma GCC system_header +# pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) namespace ranges { -template -concept __zip_is_common = (sizeof...(_Rs) == 1 && (common_range<_Rs> && ...)) || - (!(bidirectional_range<_Rs> && ...) && (common_range<_Rs> && ...)) || - ((random_access_range<_Rs> && ...) && (sized_range<_Rs> && ...)); - -template -auto __tuple_or_pair_test() -> pair<_T, _U>; - -template -requires(sizeof...(_Ts) != 2) auto __tuple_or_pair_test() -> tuple<_Ts...>; - -template -using __tuple_or_pair = decltype(__tuple_or_pair_test<_Ts...>()); - -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_F&& __f, _Tuple&& __tuple) { - return apply( - [&](_Ts&&... __elements) { - return __tuple_or_pair...>( - invoke(__f, static_cast<_Ts&&>(__elements))...); - }, - static_cast<_Tuple&&>(__tuple)); +template +concept __zip_is_common = (sizeof...(_Ranges) == 1 && (common_range<_Ranges> && ...)) || + (!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) || + ((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...)); + +template +auto __tuple_or_pair_test() -> pair<_Tp, _Up>; + +template + requires(sizeof...(_Types) != 2) +auto __tuple_or_pair_test() -> tuple<_Types...>; + +template +using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>()); + +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) { + return std::apply( + [&](_Types&&... __elements) { + return __tuple_or_pair...>( + std::invoke(__f, std::forward<_Types>(__elements))...); + }, + std::forward<_Tuple>(__tuple)); } -template -_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_F&& __f, _Tuple&& __tuple) { - apply([&]( - _Ts&&... __elements) { (invoke(__f, static_cast<_Ts&&>(__elements)), ...); }, - static_cast<_Tuple&&>(__tuple)); +template +_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tuple) { + std::apply( + [&](_Types&&... __elements) { (std::invoke(__f, std::forward<_Types>(__elements)), ...); }, + std::forward<_Tuple>(__tuple)); } - -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_F&& __f, - _Tuple1&& __tuple1, - _Tuple2&& __tuple2, - index_sequence) { - return __tuple_or_pair< - invoke_result_t<_F&, typename tuple_element>::type, - typename tuple_element>::type>...>{ - invoke(__f, get(static_cast<_Tuple1&&>(__tuple1)), - get(static_cast<_Tuple2&&>(__tuple2)))...}; +template +_LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair< + invoke_result_t<_Fun&, typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type, + typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...> +__tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, index_sequence<_Indices...>) { + return {std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), + std::get<_Indices>(std::forward<_Tuple2>(__tuple2)))...}; } -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_F&& __f, - _Tuple1&& __tuple1, - _Tuple2&& __tuple2) { - return __tuple_zip_transform(__f, static_cast<_Tuple1&&>(__tuple1), - static_cast<_Tuple2&&>(__tuple2), - make_index_sequence>::value>()); +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { + return __tuple_zip_transform(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2), + make_index_sequence>::value>()); } -template -_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_zip_for_each(_F&& __f, - _Tuple1&& __tuple1, - _Tuple2&& __tuple2, - index_sequence) { - (invoke(__f, get(static_cast<_Tuple1&&>(__tuple1)), - get(static_cast<_Tuple2&&>(__tuple2))), - ...); +template +_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, + index_sequence<_Indices...>) { + (std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), + std::get<_Indices>(std::forward<_Tuple2>(__tuple2))), + ...); } -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_for_each(_F&& __f, - _Tuple1&& __tuple1, - _Tuple2&& __tuple2) { - return __tuple_zip_for_each(__f, static_cast<_Tuple1&&>(__tuple1), - static_cast<_Tuple2&&>(__tuple2), - make_index_sequence>::value>()); +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { + return __tuple_zip_for_each(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2), + make_index_sequence>::value>()); } // abs in cstdlib is not constexpr -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __abs(_T t) { - return t < 0 ? -t : t; +// TODO : remove __abs once P0533R9 is implemented. +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __abs(_Tp t) { + return t < 0 ? -t : t; } template - requires(view<_Views>&&...) && (sizeof...(_Views) > 0) class zip_view - : public view_interface> { - - tuple<_Views...> __views_; - - template - class __iterator; - - template - class __sentinel; - - public: - _LIBCPP_HIDE_FROM_ABI - zip_view() = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit zip_view(_Views... __views) - : __views_(std::move(__views)...) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr auto begin() requires(!(__simple_view<_Views> && ...)) { - return __iterator(__tuple_transform(ranges::begin, __views_)); - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto begin() const requires(range&&...) { - return __iterator(__tuple_transform(ranges::begin, __views_)); - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto end() requires(!(__simple_view<_Views> && ...)) { - if constexpr (!__zip_is_common<_Views...>) { - return __sentinel(__tuple_transform(ranges::end, __views_)); - } else if constexpr ((random_access_range<_Views> && ...)) { - return begin() + iter_difference_t<__iterator>(size()); - } else { - return __iterator(__tuple_transform(ranges::end, __views_)); - } - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto end() const requires(range&&...) { - if constexpr (!__zip_is_common) { - return __sentinel(__tuple_transform(ranges::end, __views_)); - } else if constexpr ((random_access_range && ...)) { - return begin() + iter_difference_t<__iterator>(size()); - } else { - return __iterator(__tuple_transform(ranges::end, __views_)); - } - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto size() requires(sized_range<_Views>&&...) { - return apply( - [](auto... sizes) { - using CT = make_unsigned_t>; - return min({CT(sizes)...}); - }, - __tuple_transform(ranges::size, __views_)); - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto size() const requires(sized_range&&...) { - return apply( - [](auto... sizes) { - using CT = make_unsigned_t>; - return min({CT(sizes)...}); - }, - __tuple_transform(ranges::size, __views_)); - } + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +class zip_view : public view_interface> { + + _LIBCPP_NO_UNIQUE_ADDRESS tuple<_Views...> __views_; + + template + class __iterator; + + template + class __sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI + zip_view() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit zip_view(_Views... __views) : __views_(std::move(__views)...) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() + requires(!(__simple_view<_Views> && ...)) + { + return __iterator(__tuple_transform(ranges::begin, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() const + requires(range && ...) + { + return __iterator(__tuple_transform(ranges::begin, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() + requires(!(__simple_view<_Views> && ...)) + { + if constexpr (!__zip_is_common<_Views...>) { + return __sentinel(__tuple_transform(ranges::end, __views_)); + } else if constexpr ((random_access_range<_Views> && ...)) { + return begin() + iter_difference_t<__iterator>(size()); + } else { + return __iterator(__tuple_transform(ranges::end, __views_)); + } + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() const + requires(range && ...) + { + if constexpr (!__zip_is_common) { + return __sentinel(__tuple_transform(ranges::end, __views_)); + } else if constexpr ((random_access_range && ...)) { + return begin() + iter_difference_t<__iterator>(size()); + } else { + return __iterator(__tuple_transform(ranges::end, __views_)); + } + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() + requires(sized_range<_Views> && ...) + { + return std::apply( + [](auto... __sizes) { + using _CT = make_unsigned_t>; + return ranges::min({_CT(__sizes)...}); + }, + __tuple_transform(ranges::size, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() const + requires(sized_range && ...) + { + return std::apply( + [](auto... __sizes) { + using _CT = make_unsigned_t>; + return ranges::min({_CT(__sizes)...}); + }, + __tuple_transform(ranges::size, __views_)); + } }; -template -zip_view(_Rs&&...) -> zip_view...>; +template +zip_view(_Ranges&&...) -> zip_view...>; template concept __zip_all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...); @@ -197,297 +213,303 @@ concept __zip_all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); template -consteval auto __zip_view_iterator_concept_test() { - if constexpr (__zip_all_random_access<_Const, _Views...>) { - return random_access_iterator_tag(); - } else if constexpr (__zip_all_bidirectional<_Const, _Views...>) { - return bidirectional_iterator_tag(); - } else if constexpr (__zip_all_forward<_Const, _Views...>) { - return forward_iterator_tag(); - } else { - return input_iterator_tag(); - } +consteval auto __get_zip_view_iterator_tag() { + if constexpr (__zip_all_random_access<_Const, _Views...>) { + return random_access_iterator_tag(); + } else if constexpr (__zip_all_bidirectional<_Const, _Views...>) { + return bidirectional_iterator_tag(); + } else if constexpr (__zip_all_forward<_Const, _Views...>) { + return forward_iterator_tag(); + } else { + return input_iterator_tag(); + } } template struct __zip_view_iterator_category_base {}; template -requires __zip_all_forward<_Const, _Views...> // - struct __zip_view_iterator_category_base<_Const, _Views...> { - using iterator_category = input_iterator_tag; + requires __zip_all_forward<_Const, _Views...> +struct __zip_view_iterator_category_base<_Const, _Views...> { + using iterator_category = input_iterator_tag; }; template - requires(view<_Views>&&...) && (sizeof...(_Views) > 0) // - template - class zip_view<_Views...>::__iterator - : public __zip_view_iterator_category_base<_Const, _Views...> { - - __tuple_or_pair>...> __current_; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __iterator( - __tuple_or_pair>...> __current) - : __current_(std::move(__current)) {} - - template - friend class zip_view<_Views...>::__iterator; - - template - friend class zip_view<_Views...>::__sentinel; - - friend class zip_view<_Views...>; - - public: - using iterator_concept = decltype(__zip_view_iterator_concept_test<_Const, _Views...>()); - using value_type = __tuple_or_pair>...>; - using difference_type = common_type_t>...>; - - _LIBCPP_HIDE_FROM_ABI - __iterator() = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(__iterator __i) requires _Const && - (convertible_to, iterator_t<__maybe_const<_Const, _Views>>> && ...) - : __current_(std::move(__i.__current_)) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr auto operator*() const { - return __tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_); - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { - __tuple_for_each([](auto& __i) { ++__i; }, __current_); - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr void operator++(int) { - ++*this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) requires __zip_all_forward<_Const, _Views...> { - auto __tmp = *this; - ++*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() requires __zip_all_bidirectional<_Const, _Views...> { - __tuple_for_each([](auto& __i) { --__i; }, __current_); - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) requires __zip_all_bidirectional<_Const, _Views...> { - auto __tmp = *this; - --*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator+=(difference_type __x) requires - __zip_all_random_access<_Const, _Views...> { - __tuple_for_each([&](_I& __i) { __i += iter_difference_t<_I>(__x); }, __current_); - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator-=(difference_type __x) requires - __zip_all_random_access<_Const, _Views...> { - __tuple_for_each([&](_I& __i) { __i -= iter_difference_t<_I>(__x); }, __current_); - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr auto operator[](difference_type __n) const requires - __zip_all_random_access<_Const, _Views...> { - return __tuple_transform( - [&](_I& __i) -> decltype(auto) { return __i[iter_difference_t<_I>(__n)]; }, - __current_); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) - requires(equality_comparable>>&&...) { - if constexpr (__zip_all_bidirectional<_Const, _Views...>) { - return __x.__current_ == __y.__current_; - } else { - const auto __it_equals = - __tuple_zip_transform(std::equal_to<>(), __x.__current_, __y.__current_); - return apply([](auto... bs) { return (bs || ...); }, __it_equals); - } - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) requires - __zip_all_random_access<_Const, _Views...> { - return __x.__current_ < __y.__current_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) requires - __zip_all_random_access<_Const, _Views...> { - return __y < __x; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) requires - __zip_all_random_access<_Const, _Views...> { - return !(__y < __x); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) requires - __zip_all_random_access<_Const, _Views...> { - return !(__x < __y); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) requires - __zip_all_random_access<_Const, _Views...> && - (three_way_comparable>> && ...) { - // clang-format off - return __x.__current_ <=> __y.__current_; - // clang-format on - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) requires - __zip_all_random_access<_Const, _Views...> { - auto __r = __i; - __r += __n; - return __r; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) requires - __zip_all_random_access<_Const, _Views...> { - auto __r = __i; - __r += __n; - return __r; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) requires - __zip_all_random_access<_Const, _Views...> { - auto __r = __i; - __r -= __n; - return __r; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) - requires(sized_sentinel_for>, - iterator_t<__maybe_const<_Const, _Views>>>&&...) { - const auto __diffs = __tuple_zip_transform(std::minus<>(), __x.__current_, __y.__current_); - return apply( - [](auto... ds) { - return min({difference_type(ds)...}, - [](auto x, auto y) { return __abs(x) < __abs(y); }); - }, - __diffs); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr auto iter_move(const __iterator& __i) noexcept( - (noexcept(ranges::iter_move(declval>&>())) && - ...) && - (is_nothrow_move_constructible_v>> && - ...)) { - return __tuple_transform(ranges::iter_move, __i.__current_); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( - (noexcept(ranges::iter_swap(declval>&>(), - declval>&>())) && - ...)) requires(indirectly_swappable>>&&...) { - __tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); - } + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +template +class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> { + + __tuple_or_pair>...> __current_; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __iterator(__tuple_or_pair>...> __current) + : __current_(std::move(__current)) {} + + template + friend class zip_view<_Views...>::__iterator; + + template + friend class zip_view<_Views...>::__sentinel; + + friend class zip_view<_Views...>; + +public: + using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>()); + using value_type = __tuple_or_pair>...>; + using difference_type = common_type_t>...>; + + _LIBCPP_HIDE_FROM_ABI + __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator(__iterator __i) + requires _Const && (convertible_to, iterator_t<__maybe_const<_Const, _Views>>> && ...) + : __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator*() const { + return __tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator++() { + __tuple_for_each([](auto& __i) { ++__i; }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator++(int) + requires __zip_all_forward<_Const, _Views...> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator--() + requires __zip_all_bidirectional<_Const, _Views...> + { + __tuple_for_each([](auto& __i) { --__i; }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator--(int) + requires __zip_all_bidirectional<_Const, _Views...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator+=(difference_type __x) + requires __zip_all_random_access<_Const, _Views...> + { + __tuple_for_each([&](_Iter& __i) { __i += iter_difference_t<_Iter>(__x); }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator-=(difference_type __x) + requires __zip_all_random_access<_Const, _Views...> + { + __tuple_for_each([&](_Iter& __i) { __i -= iter_difference_t<_Iter>(__x); }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator[](difference_type __n) const + requires __zip_all_random_access<_Const, _Views...> + { + return __tuple_transform( + [&](_Iter& __i) -> decltype(auto) { return __i[iter_difference_t<_Iter>(__n)]; }, __current_); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires(equality_comparable>> && ...) + { + if constexpr (__zip_all_bidirectional<_Const, _Views...>) { + return __x.__current_ == __y.__current_; + } else { + const auto __it_equals = __tuple_zip_transform(std::equal_to<>(), __x.__current_, __y.__current_); + return std::apply([](auto... __bs) { return (__bs || ...); }, __it_equals); + } + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> + { + return __x.__current_ < __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> && + (three_way_comparable>> && ...) + { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) + requires __zip_all_random_access<_Const, _Views...> + { + auto __r = __i; + __r += __n; + return __r; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) + requires __zip_all_random_access<_Const, _Views...> + { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) + requires __zip_all_random_access<_Const, _Views...> + { + auto __r = __i; + __r -= __n; + return __r; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires(sized_sentinel_for>, iterator_t<__maybe_const<_Const, _Views>>> && + ...) + { + const auto __diffs = __tuple_zip_transform(std::minus<>(), __x.__current_, __y.__current_); + return std::apply( + [](auto... __ds) { + return ranges::min({difference_type(__ds)...}, [](auto __a, auto __b) { return __abs(__a) < __abs(__b); }); + }, + __diffs); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto iter_move(const __iterator& __i) noexcept( + (noexcept(ranges::iter_move(declval>&>())) && ...) && + (is_nothrow_move_constructible_v>> && ...)) { + return __tuple_transform(ranges::iter_move, __i.__current_); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( + (noexcept(ranges::iter_swap(declval>&>(), + declval>&>())) && + ...)) + requires(indirectly_swappable>> && ...) + { + __tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); + } }; template - requires(view<_Views>&&...) && (sizeof...(_Views) > 0) // - template - class zip_view<_Views...>::__sentinel { - - __tuple_or_pair>...> __end_; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel( - __tuple_or_pair>...> __end) - : __end_(__end) {} - - friend class zip_view<_Views...>; - - // hidden friend cannot access private member of iterator because - // they are friends of friends - template - _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __iter_current( - zip_view<_Views...>::__iterator<_OtherConst> const& __it) { - return __it.__current_; - } - - public: - _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; - constexpr __sentinel(__sentinel __i) requires _Const && - (convertible_to, sentinel_t<__maybe_const<_Const, _Views>>> && ...) - : __end_(std::move(__i.__end_)) {} - - template - requires(sentinel_for>, - iterator_t<__maybe_const<_OtherConst, _Views>>>&&...) - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { - const auto __it_equals = - __tuple_zip_transform(std::equal_to<>(), __iter_current(__x), __y.__end_); - return apply([](auto... bs) { return (bs || ...); }, __it_equals); - } - - template - requires(sized_sentinel_for>, - iterator_t<__maybe_const<_OtherConst, _Views>>>&&...) - _LIBCPP_HIDE_FROM_ABI - friend constexpr common_type_t>...> - operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { - const auto __diffs = __tuple_zip_transform(std::minus<>(), __iter_current(__x), __y.__end_); - return apply( - [](auto... ds) { - using D = common_type_t>...>; - return min({D(ds)...}, [](auto x, auto y) { return __abs(x) < __abs(y); }); - }, - __diffs); - } - - template - requires(sized_sentinel_for>, - iterator_t<__maybe_const<_OtherConst, _Views>>>&&...) - _LIBCPP_HIDE_FROM_ABI - friend constexpr common_type_t>...> - operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) { - return -(__x - __y); - } + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +template +class zip_view<_Views...>::__sentinel { + + __tuple_or_pair>...> __end_; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __sentinel(__tuple_or_pair>...> __end) : __end_(__end) {} + + friend class zip_view<_Views...>; + + // hidden friend cannot access private member of iterator because + // they are friends of friends + template + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) + __iter_current(zip_view<_Views...>::__iterator<_OtherConst> const& __it) { + return __it.__current_; + } + +public: + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr __sentinel(__sentinel __i) + requires _Const && (convertible_to, sentinel_t<__maybe_const<_Const, _Views>>> && ...) + : __end_(std::move(__i.__end_)) {} + + template + requires(sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + const auto __it_equals = __tuple_zip_transform(std::equal_to<>(), __iter_current(__x), __y.__end_); + return std::apply([](auto... bs) { return (bs || ...); }, __it_equals); + } + + template + requires( + sized_sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t>...> + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + const auto __diffs = __tuple_zip_transform(std::minus<>(), __iter_current(__x), __y.__end_); + return std::apply( + [](auto... __ds) { + using _Diff = common_type_t>...>; + return ranges::min({_Diff(__ds)...}, [](auto __a, auto __b) { return __abs(__a) < __abs(__b); }); + }, + __diffs); + } + + template + requires( + sized_sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t>...> + operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) { + return -(__x - __y); + } }; +template +inline constexpr bool enable_borrowed_range> = (enable_borrowed_range<_Views> && ...); + namespace views { namespace __zip { struct __fn { - _LIBCPP_HIDE_FROM_ABI constexpr auto operator()() const noexcept { - return empty_view>{}; - } + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()() const noexcept { return empty_view>{}; } - template - _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Rs&&... rs) const - noexcept(noexcept(zip_view(static_cast<_Rs&&>(rs)...))) - -> decltype(zip_view(static_cast<_Rs&&>(rs)...)) { - return zip_view(static_cast<_Rs&&>(rs)...); - } + template + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ranges&&... rs) const + noexcept(noexcept(zip_view(std::forward<_Ranges>(rs)...))) -> decltype(zip_view(std::forward<_Ranges>(rs)...)) { + return zip_view(std::forward<_Ranges>(rs)...); + } }; } // namespace __zip @@ -500,10 +522,10 @@ } // namespace ranges - - #endif // _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___RANGES_ZIP_VIEW_H \ No newline at end of file +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ZIP_VIEW_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -848,7 +848,7 @@ } module view_interface { private header "__ranges/view_interface.h" } module views { private header "__ranges/views.h" } - module zip { private header "__ranges/zip_view.h" } + module zip_view { private header "__ranges/zip_view.h" } } } module ratio { diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -196,6 +196,18 @@ template requires view && input_range> class join_view; + + // C++2b + // [range.zip], zip view + template + requires (view && ...) && (sizeof...(Views) > 0) + class zip_view; + + template + inline constexpr bool enable_borrowed_range> = + (enable_borrowed_range && ...); + + namespace views { inline constexpr unspecified zip = unspecified; } } namespace std { 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 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include "test_macros.h" @@ -50,4 +51,4 @@ int main(int, char**) { test(); static_assert(test()); -} \ No newline at end of file +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// template +// inline constexpr bool enable_borrowed_range> = +// (enable_borrowed_range && ...); + +#include +#include + +struct Borrowed : std::ranges::view_base { + int* begin() const; + int* end() const; +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +static_assert(std::ranges::borrowed_range); + +struct NonBorrowed : std::ranges::view_base { + int* begin() const; + int* end() const; +}; +static_assert(!std::ranges::borrowed_range); + +void testBorrowedRange() { + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(!std::ranges::borrowed_range>); +} 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 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/ctad.compile.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.zip/ctad.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/ctad.compile.pass.cpp @@ -9,14 +9,16 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // UNSUPPORTED: libcpp-has-no-incomplete-ranges -// template -// zip_view(_Rs&&...) -> zip_view...>; +// template +// zip_view(Rs&&...) -> zip_view...>; #include #include #include #include +#include "test_macros.h" + struct Container { int* begin() const; int* end() const; @@ -28,14 +30,13 @@ }; void testCTAD() { - static_assert(std::same_as>>); + ASSERT_SAME_TYPE(decltype(std::ranges::zip_view(Container{})), + std::ranges::zip_view>); - static_assert(std::same_as, View>>); + ASSERT_SAME_TYPE(decltype(std::ranges::zip_view(Container{}, View{})), + std::ranges::zip_view, View>); Container c{}; - static_assert( - std::same_as, View, std::ranges::ref_view>>); -} \ No newline at end of file + ASSERT_SAME_TYPE(decltype(std::ranges::zip_view(Container{}, View{}, c)), + std::ranges::zip_view, View, std::ranges::ref_view>); +} diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.default.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/ctor.default.pass.cpp @@ -15,6 +15,7 @@ #include #include +#include constexpr int buff[] = {1, 2, 3}; 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 --- 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 @@ -12,7 +12,9 @@ // constexpr explicit zip_view(Views...) #include +#include +#include "test_macros.h" #include "types.h" constexpr bool test() { diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/general.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.zip/general.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/general.pass.cpp @@ -35,7 +35,7 @@ { using namespace std::string_literals; std::vector v{1, 2, 3, 4}; - std::array a{"abc", "def", "gh"}; + std::array a{"abc"s, "def"s, "gh"s}; auto view = std::views::zip(v, a); auto it = view.begin(); assert(&(std::get<0>(*it)) == &(v[0])); @@ -52,4 +52,6 @@ ++it; assert(it == view.end()); } -} \ No newline at end of file + + return 0; +} 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 --- 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 @@ -11,12 +11,15 @@ // x += n; // x + n; +// n + x; // x -= n; // x - n; // x - y; #include +#include + #include "test_macros.h" #include "../types.h" @@ -33,6 +36,11 @@ assert(&x2 == &(a[3])); assert(&y2 == &(b[3])); + auto it3 = 3 + it1; + auto [x3, y3] = *it3; + assert(&x3 == &(a[3])); + assert(&y3 == &(b[3])); + it1 += 3; assert(it1 == it2); auto [x1, y1] = *it2; 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 --- 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 @@ -60,11 +60,9 @@ assert(iter1 != iter2); assert(!(iter2 != iter2)); - // clang-format off - assert((iter1 <=> iter2) == std::strong_ordering::less); - assert((iter1 <=> iter1) == std::strong_ordering::equal); - assert((iter2 <=> iter1) == std::strong_ordering::greater); - // clang-format on + assert((iter1 <=> iter2) == std::strong_ordering::less); + assert((iter1 <=> iter1) == std::strong_ordering::equal); + assert((iter2 <=> iter1) == std::strong_ordering::greater); } { 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 --- 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 @@ -12,6 +12,7 @@ // iterator() = default; #include +#include #include "test_macros.h" #include "../types.h" @@ -55,5 +56,6 @@ int main(int, char**) { test(); static_assert(test()); + return 0; } 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 --- 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 @@ -14,6 +14,7 @@ #include #include +#include #include "test_macros.h" #include "../types.h" 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 --- 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 @@ -12,9 +12,10 @@ // constexpr iterator& operator--(); // constexpr iterator operator--(int); +#include #include #include -#include +#include #include "test_macros.h" #include "../types.h" @@ -39,7 +40,9 @@ using Iter = decltype(it); ASSERT_SAME_TYPE(decltype(--it), Iter&); - --it; + auto& it_ref = --it; + assert(&it_ref == &it); + assert(&(std::get<0>(*it)) == &(a[2])); assert(&(std::get<1>(*it)) == &(b[2])); assert(std::get<2>(*it) == 2); @@ -64,4 +67,4 @@ static_assert(test()); return 0; -} \ No newline at end of file +} 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 --- 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 @@ -11,9 +11,10 @@ // constexpr auto operator*() const; +#include #include #include -#include +#include #include "test_macros.h" #include "../types.h" 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 --- 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 @@ -13,9 +13,10 @@ // constexpr void operator++(int); // constexpr iterator operator++(int) requires all_forward; +#include #include #include -#include +#include #include "test_macros.h" #include "../types.h" @@ -42,7 +43,9 @@ ASSERT_SAME_TYPE(decltype(++it), Iter&); - ++it; + auto& it_ref = ++it; + assert(&it_ref == &it); + assert(&(std::get<0>(*it)) == &(a[1])); assert(&(std::get<1>(*it)) == &(b[1])); assert(std::get<2>(*it) == 1); @@ -80,4 +83,4 @@ static_assert(test()); return 0; -} \ No newline at end of file +} 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 --- 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 @@ -13,7 +13,9 @@ #include #include +#include #include +#include #include "test_macros.h" #include "../types.h" 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 --- 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 @@ -11,6 +11,7 @@ // friend constexpr void iter_swap(const iterator& x, const iterator& y); +#include #include #include 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 --- 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 @@ -12,9 +12,11 @@ // Iterator traits and member typedefs in zip_view::. #include +#include #include "test_iterators.h" #include "test_macros.h" + #include "../types.h" template diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.default.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/ctor.default.pass.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "test_macros.h" #include "../types.h" 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 --- 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 @@ -16,6 +16,7 @@ #include #include #include +#include #include "test_macros.h" #include "../types.h" 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 --- 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 @@ -21,11 +21,13 @@ // friend constexpr common_type_t>...> // operator-(const sentinel&, const iterator&) -#include #include +#include +#include #include "test_macros.h" #include "test_iterators.h" + #include "../types.h" template diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/types.h b/libcxx/test/std/ranges/range.adaptors/range.zip/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.zip/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/types.h @@ -1,11 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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_TYPES_H #define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TYPES_H -#include +#if TEST_STD_VER > 17 + +# include -#include "test_macros.h" -#include "test_iterators.h" -#include "test_range.h" +# include "test_macros.h" +# include "test_iterators.h" +# include "test_range.h" struct IntBuffer { int* buffer_; @@ -218,4 +228,6 @@ static_assert(std::ranges::random_access_range); static_assert(std::ranges::sized_range); +#endif // TEST_STD_VER > 17 + #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_ZIP_TYPES_H