Skip to content

Commit cbe0364

Browse files
[libc++][ranges] LWG3692: zip_view::iterator's operator<=> is overconstrained and changes of zip_view in P2165R4 (#112077)
The changes are nearly pure simplifications, so I think it's OK to do them together in the same PR. Actual test coverages were already added in commit ad41d1e (https://reviews.llvm.org/D141216). Thanks to Casey Carter! Fixes #104975 Towards #105200
1 parent e839d2a commit cbe0364

File tree

9 files changed

+13
-102
lines changed

9 files changed

+13
-102
lines changed

libcxx/docs/Status/Cxx23Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@
168168
"`LWG3672 <https://wg21.link/LWG3672>`__","``common_iterator::operator->()`` should return by value","2022-07 (Virtual)","|Complete|","19.0",""
169169
"`LWG3683 <https://wg21.link/LWG3683>`__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","2022-07 (Virtual)","|Complete|","20.0",""
170170
"`LWG3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","2022-07 (Virtual)","|Complete|","16.0",""
171-
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","","",""
171+
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20.0",""
172172
"`LWG3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15.0",""
173173
"`LWG3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","",""
174174
"`LWG3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","2022-07 (Virtual)","|Complete|","16.0",""

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"`P1642R11 <https://wg21.link/P1642R11>`__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","",""
6161
"`P1899R3 <https://wg21.link/P1899R3>`__","``stride_view``","2022-07 (Virtual)","","",""
6262
"`P2093R14 <https://wg21.link/P2093R14>`__","Formatted output","2022-07 (Virtual)","|Complete|","18.0",""
63-
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","","",""
63+
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Only the part for ``zip_view`` is implemented."
6464
"`P2278R4 <https://wg21.link/P2278R4>`__","``cbegin`` should always return a constant iterator","2022-07 (Virtual)","","",""
6565
"`P2286R8 <https://wg21.link/P2286R8>`__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16.0",""
6666
"`P2291R3 <https://wg21.link/P2291R3>`__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ``<charconv>`` Header","2022-07 (Virtual)","|Complete|","16.0",""

libcxx/include/__ranges/zip_view.h

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include <__utility/forward.h>
3737
#include <__utility/integer_sequence.h>
3838
#include <__utility/move.h>
39-
#include <__utility/pair.h>
4039
#include <tuple>
4140

4241
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -58,22 +57,11 @@ concept __zip_is_common =
5857
(!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) ||
5958
((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...));
6059

61-
template <typename _Tp, typename _Up>
62-
auto __tuple_or_pair_test() -> pair<_Tp, _Up>;
63-
64-
template <typename... _Types>
65-
requires(sizeof...(_Types) != 2)
66-
auto __tuple_or_pair_test() -> tuple<_Types...>;
67-
68-
template <class... _Types>
69-
using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>());
70-
7160
template <class _Fun, class _Tuple>
7261
_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) {
7362
return std::apply(
7463
[&]<class... _Types>(_Types&&... __elements) {
75-
return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>(
76-
std::invoke(__f, std::forward<_Types>(__elements))...);
64+
return tuple<invoke_result_t<_Fun&, _Types>...>(std::invoke(__f, std::forward<_Types>(__elements))...);
7765
},
7866
std::forward<_Tuple>(__tuple));
7967
}
@@ -88,7 +76,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tup
8876
}
8977

9078
template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices>
91-
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair<
79+
_LIBCPP_HIDE_FROM_ABI constexpr tuple<
9280
invoke_result_t<_Fun&,
9381
typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type,
9482
typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...>
@@ -250,10 +238,9 @@ template <input_range... _Views>
250238
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
251239
template <bool _Const>
252240
class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> {
253-
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_;
241+
tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current_;
254242

255-
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(
256-
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current)
243+
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current)
257244
: __current_(std::move(__current)) {}
258245

259246
template <bool>
@@ -266,7 +253,7 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base
266253

267254
public:
268255
using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>());
269-
using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>;
256+
using value_type = tuple<range_value_t<__maybe_const<_Const, _Views>>...>;
270257
using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>;
271258

272259
_LIBCPP_HIDE_FROM_ABI __iterator() = default;
@@ -340,33 +327,8 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base
340327
}
341328
}
342329

343-
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
344-
requires __zip_all_random_access<_Const, _Views...>
345-
{
346-
return __x.__current_ < __y.__current_;
347-
}
348-
349-
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
350-
requires __zip_all_random_access<_Const, _Views...>
351-
{
352-
return __y < __x;
353-
}
354-
355-
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
356-
requires __zip_all_random_access<_Const, _Views...>
357-
{
358-
return !(__y < __x);
359-
}
360-
361-
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
362-
requires __zip_all_random_access<_Const, _Views...>
363-
{
364-
return !(__x < __y);
365-
}
366-
367330
_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
368-
requires __zip_all_random_access<_Const, _Views...> &&
369-
(three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...)
331+
requires __zip_all_random_access<_Const, _Views...>
370332
{
371333
return __x.__current_ <=> __y.__current_;
372334
}
@@ -427,10 +389,9 @@ template <input_range... _Views>
427389
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
428390
template <bool _Const>
429391
class zip_view<_Views...>::__sentinel {
430-
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;
392+
tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;
431393

432-
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(
433-
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
394+
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
434395
: __end_(__end) {}
435396

436397
friend class zip_view<_Views...>;

libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,7 @@ constexpr bool test() {
6363
std::ranges::zip_view<std::ranges::zip_view<SizedRandomAccessView, SizedRandomAccessView>>> decltype(auto) v2 =
6464
std::views::zip(v);
6565

66-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
67-
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::pair<int&, int&>>>);
68-
#else
6966
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::tuple<int&, int&>>>);
70-
#endif
7167
}
7268
return true;
7369
}

libcxx/test/std/ranges/range.adaptors/range.zip/ctor.default.pass.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,8 @@ constexpr bool test() {
4949
using View = std::ranges::zip_view<DefaultConstructibleView, DefaultConstructibleView>;
5050
View v = View(); // the default constructor is not explicit
5151
assert(v.size() == 3);
52-
auto it = v.begin();
53-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
54-
using Value = std::pair<const int&, const int&>;
55-
#else
52+
auto it = v.begin();
5653
using Value = std::tuple<const int&, const int&>;
57-
#endif
5854
assert(*it++ == Value(buff[0], buff[0]));
5955
assert(*it++ == Value(buff[1], buff[1]));
6056
assert(*it == Value(buff[2], buff[2]));

libcxx/test/std/ranges/range.adaptors/range.zip/iterator/compare.pass.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,8 @@
1010

1111
// friend constexpr bool operator==(const iterator& x, const iterator& y)
1212
// requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
13-
// friend constexpr bool operator<(const iterator& x, const iterator& y)
14-
// requires all-random-access<Const, Views...>;
15-
// friend constexpr bool operator>(const iterator& x, const iterator& y)
16-
// requires all-random-access<Const, Views...>;
17-
// friend constexpr bool operator<=(const iterator& x, const iterator& y)
18-
// requires all-random-access<Const, Views...>;
19-
// friend constexpr bool operator>=(const iterator& x, const iterator& y)
20-
// requires all-random-access<Const, Views...>;
2113
// friend constexpr auto operator<=>(const iterator& x, const iterator& y)
22-
// requires all-random-access<Const, Views...> &&
23-
// (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
14+
// requires all-random-access<Const, Views...>;
2415

2516
#include <ranges>
2617
#include <compare>
@@ -165,12 +156,7 @@ constexpr bool test() {
165156
using Subrange = std::ranges::subrange<It>;
166157
static_assert(!std::three_way_comparable<It>);
167158
using R = std::ranges::zip_view<Subrange, Subrange>;
168-
#ifdef _LIBCPP_VERSION
169-
// libc++ hasn't implemented LWG-3692 "zip_view::iterator's operator<=> is overconstrained"
170-
static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
171-
#else
172159
static_assert(std::three_way_comparable<std::ranges::iterator_t<R>>);
173-
#endif
174160

175161
int a[] = {1, 2, 3, 4};
176162
int b[] = {5, 6, 7, 8, 9};

libcxx/test/std/ranges/range.adaptors/range.zip/iterator/deref.pass.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ constexpr bool test() {
4242
auto [x, y] = *it;
4343
assert(&x == &(a[0]));
4444
assert(&y == &(b[0]));
45-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
46-
static_assert(std::is_same_v<decltype(*it), std::pair<int&, double&>>);
47-
#else
4845
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, double&>>);
49-
#endif
5046

5147
x = 5;
5248
y = 0.1;
@@ -70,11 +66,7 @@ constexpr bool test() {
7066
auto it = v.begin();
7167
assert(&(std::get<0>(*it)) == &(a[0]));
7268
assert(&(std::get<1>(*it)) == &(a[0]));
73-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
74-
static_assert(std::is_same_v<decltype(*it), std::pair<int&, int const&>>);
75-
#else
7669
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, int const&>>);
77-
#endif
7870
}
7971
return true;
8072
}

libcxx/test/std/ranges/range.adaptors/range.zip/iterator/member_types.compile.pass.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,15 @@ struct ConstVeryDifferentRange {
6565
void test() {
6666
int buffer[] = {1, 2, 3, 4};
6767
{
68-
// 2 views should have pair value_type
68+
// 2 views should have 2-tuple value_type
6969
// random_access_iterator_tag
7070
std::ranges::zip_view v(buffer, buffer);
7171
using Iter = decltype(v.begin());
7272

7373
static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
7474
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
7575
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
76-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
77-
static_assert(std::is_same_v<Iter::value_type, std::pair<int, int>>);
78-
#else
7976
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, int>>);
80-
#endif
8177
static_assert(HasIterCategory<Iter>);
8278
}
8379

@@ -124,11 +120,7 @@ void test() {
124120
static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
125121
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
126122
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
127-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
128-
static_assert(std::is_same_v<Iter::value_type, std::pair<int, std::pair<int, int>>>);
129-
#else
130123
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, std::tuple<int, int>>>);
131-
#endif
132124
static_assert(HasIterCategory<Iter>);
133125
}
134126

@@ -169,11 +161,7 @@ void test() {
169161
// value_type of multiple views with different value_type
170162
std::ranges::zip_view v{foos, bars};
171163
using Iter = decltype(v.begin());
172-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
173-
static_assert(std::is_same_v<Iter::value_type, std::pair<Foo, Bar>>);
174-
#else
175164
static_assert(std::is_same_v<Iter::value_type, std::tuple<Foo, Bar>>);
176-
#endif
177165
}
178166

179167
{

libcxx/test/std/ranges/range.adaptors/range.zip/iterator/subscript.pass.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ constexpr bool test() {
2727
assert(it[2] == *(it + 2));
2828
assert(it[4] == *(it + 4));
2929

30-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
31-
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int>>);
32-
#else
3330
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int>>);
34-
#endif
3531
}
3632

3733
{
@@ -42,11 +38,7 @@ constexpr bool test() {
4238
assert(it[2] == *(it + 2));
4339
assert(it[4] == *(it + 4));
4440

45-
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
46-
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int&>>);
47-
#else
4841
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int&>>);
49-
#endif
5042
}
5143

5244
{

0 commit comments

Comments
 (0)