[libcxx-commits] [libcxx] [libc++][ranges][enumerate_view] Fix iterator converting constructor test (PR #212044)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Aug 7 03:48:54 PDT 2026
https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/212044
>From a7ca704bbf976908f4c938f89d4ca63488a65cae Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 25 Jul 2026 19:28:15 +0200
Subject: [PATCH 1/5] add: static_assert for convertible_to
---
.../range.enumerate/iterator/ctor.convert.pass.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
index f441de92f6a60..083b01e178daa 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
@@ -43,6 +43,7 @@ constexpr void test() {
};
static_assert(std::is_convertible_v<EnumerateIterator, EnumerateConstIterator>);
+ static_assert(std::convertible_to<EnumerateIterator, EnumerateConstIterator>);
std::array array{0, 84, 2, 3, 4};
auto view = make_enumerate_view(array.begin(), array.end());
>From bb0f70c7a8bef2692d7ba738cc0d5890cc717a9d Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Mon, 27 Jul 2026 22:32:20 +0200
Subject: [PATCH 2/5] remove: is_convertinble_v line
---
.../range.enumerate/iterator/ctor.convert.pass.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
index 083b01e178daa..a53700b027b21 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
@@ -42,7 +42,6 @@ constexpr void test() {
return EnumerateView(std::move(view));
};
- static_assert(std::is_convertible_v<EnumerateIterator, EnumerateConstIterator>);
static_assert(std::convertible_to<EnumerateIterator, EnumerateConstIterator>);
std::array array{0, 84, 2, 3, 4};
>From 1cddab5d71fb55ccce6b88b2e6193b58040d5635 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 29 Jul 2026 23:49:54 +0200
Subject: [PATCH 3/5] port: underlying non-const to const not convertible test
case form zip view
---
.../iterator/ctor.convert.pass.cpp | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
index a53700b027b21..eda1087d0b34a 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
@@ -27,8 +27,17 @@
#include "test_iterators.h"
+#include "../../range_adaptor_types.h"
#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>>);
+
template <class Iterator, class Sentinel = sentinel_wrapper<Iterator>>
constexpr void test() {
using View = MinimalView<Iterator, Sentinel>;
@@ -64,6 +73,17 @@ constexpr void test() {
assert(index == 1);
assert(value == 84);
}
+ {
+ // underlying non-const to const not convertible
+ int buffer[3] = {1, 2, 3};
+ std::ranges::enumerate_view v(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)>);
+ }
}
constexpr bool tests() {
>From eaf043f7a597c8e831e1a04f3c9a64e75baff845 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 7 Aug 2026 00:31:02 +0200
Subject: [PATCH 4/5] ref: port zip.view tests
---
.../iterator/ctor.convert.pass.cpp | 106 ++++++++++--------
1 file changed, 62 insertions(+), 44 deletions(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
index eda1087d0b34a..954b3d6081941 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
@@ -38,44 +38,72 @@ using ConstIterIncompatibleView =
static_assert(!std::convertible_to<std::ranges::iterator_t<ConstIterIncompatibleView>,
std::ranges::iterator_t<const ConstIterIncompatibleView>>);
-template <class Iterator, class Sentinel = sentinel_wrapper<Iterator>>
-constexpr void test() {
- using View = MinimalView<Iterator, Sentinel>;
- using EnumerateView = std::ranges::enumerate_view<View>;
- using EnumerateIterator = std::ranges::iterator_t<EnumerateView>;
- using EnumerateConstIterator = std::ranges::iterator_t<const EnumerateView>;
-
- auto make_enumerate_view = [](auto begin, auto end) {
- View view{Iterator(std::to_address(base(begin))), Sentinel(Iterator(std::to_address(base(end))))};
-
- return EnumerateView(std::move(view));
- };
-
- static_assert(std::convertible_to<EnumerateIterator, EnumerateConstIterator>);
-
- std::array array{0, 84, 2, 3, 4};
- auto view = make_enumerate_view(array.begin(), array.end());
- {
- std::same_as<EnumerateIterator> decltype(auto) it = view.begin();
- std::same_as<const Iterator&> decltype(auto) itResult = it.base();
- assert(base(base(itResult)) == std::to_address(base(array.begin())));
-
- auto [index, value] = *(++it);
- assert(index == 1);
- assert(value == 84);
+struct TestIt {
+ template <class Iterator, class Sentinel = sentinel_wrapper<Iterator>>
+ constexpr void operator()() const {
+ using View = MinimalView<Iterator, Sentinel>;
+ using EnumerateView = std::ranges::enumerate_view<View>;
+ using EnumerateIterator = std::ranges::iterator_t<EnumerateView>;
+ using EnumerateConstIterator = std::ranges::iterator_t<const EnumerateView>;
+
+ auto make_enumerate_view = [](auto begin, auto end) {
+ View view{Iterator(std::to_address(base(begin))), Sentinel(Iterator(std::to_address(base(end))))};
+
+ return EnumerateView(std::move(view));
+ };
+
+ static_assert(std::convertible_to<EnumerateIterator, EnumerateConstIterator>);
+
+ std::array array{0, 84, 2, 3, 4};
+ auto view = make_enumerate_view(array.begin(), array.end());
+ {
+ std::same_as<EnumerateIterator> decltype(auto) it = view.begin();
+ std::same_as<const Iterator&> decltype(auto) itResult = it.base();
+ assert(base(base(itResult)) == std::to_address(base(array.begin())));
+
+ auto [index, value] = *(++it);
+ assert(index == 1);
+ assert(value == 84);
+ }
+ {
+ std::same_as<EnumerateConstIterator> decltype(auto) it = view.begin();
+ std::same_as<const Iterator&> decltype(auto) itResult = it.base();
+ assert(base(base(itResult)) == std::to_address(base(array.begin())));
+
+ auto [index, value] = *(++it);
+ assert(index == 1);
+ assert(value == 84);
+ }
}
+};
+
+constexpr bool
+test() {
+ using Iterators =
+ types::type_list< cpp17_input_iterator<int*>,
+ cpp20_input_iterator<int*>,
+ forward_iterator<int*>,
+ bidirectional_iterator<int*>,
+ random_access_iterator<int*>,
+ contiguous_iterator<int*>,
+ int* >;
+
+ types::for_each(Iterators{}, TestIt());
+
+ int buffer[3] = {1, 2, 3};
{
- std::same_as<EnumerateConstIterator> decltype(auto) it = view.begin();
- std::same_as<const Iterator&> decltype(auto) itResult = it.base();
- assert(base(base(itResult)) == std::to_address(base(array.begin())));
+ std::ranges::enumerate_view v(NonSimpleCommon{buffer});
+ auto iter1 = v.begin();
+ std::ranges::iterator_t<const decltype(v)> iter2 = iter1;
+ assert(iter1 == iter2);
- auto [index, value] = *(++it);
- assert(index == 1);
- assert(value == 84);
+ 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)>);
}
{
// underlying non-const to const not convertible
- int buffer[3] = {1, 2, 3};
std::ranges::enumerate_view v(ConstIterIncompatibleView{buffer});
auto iter1 = v.begin();
auto iter2 = std::as_const(v).begin();
@@ -84,23 +112,13 @@ constexpr void test() {
static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>);
static_assert(!std::constructible_from<decltype(iter2), decltype(iter1)>);
}
-}
-
-constexpr bool tests() {
- test<cpp17_input_iterator<int*>>();
- test<cpp20_input_iterator<int*>>();
- test<forward_iterator<int*>>();
- test<bidirectional_iterator<int*>>();
- test<random_access_iterator<int*>>();
- test<contiguous_iterator<int*>>();
- test<int*>();
return true;
}
int main(int, char**) {
- tests();
- static_assert(tests());
+ test();
+ static_assert(test());
return 0;
}
>From e1dda3258bfcfbc1fa91500b45c2fbea902cf4ec Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 7 Aug 2026 12:48:39 +0200
Subject: [PATCH 5/5] remove: redundant test
---
.../iterator/ctor.convert.pass.cpp | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
index 954b3d6081941..fbcefcba52220 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/iterator/ctor.convert.pass.cpp
@@ -57,15 +57,8 @@ struct TestIt {
std::array array{0, 84, 2, 3, 4};
auto view = make_enumerate_view(array.begin(), array.end());
{
- std::same_as<EnumerateIterator> decltype(auto) it = view.begin();
- std::same_as<const Iterator&> decltype(auto) itResult = it.base();
- assert(base(base(itResult)) == std::to_address(base(array.begin())));
-
- auto [index, value] = *(++it);
- assert(index == 1);
- assert(value == 84);
- }
- {
+ // Assigning a non-const iterator to a const-iterator-typed variable invokes
+ // the converting constructor.
std::same_as<EnumerateConstIterator> decltype(auto) it = view.begin();
std::same_as<const Iterator&> decltype(auto) itResult = it.base();
assert(base(base(itResult)) == std::to_address(base(array.begin())));
@@ -77,8 +70,7 @@ struct TestIt {
}
};
-constexpr bool
-test() {
+constexpr bool test() {
using Iterators =
types::type_list< cpp17_input_iterator<int*>,
cpp20_input_iterator<int*>,
@@ -97,7 +89,7 @@ test() {
std::ranges::iterator_t<const decltype(v)> iter2 = iter1;
assert(iter1 == iter2);
- static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>);
+ static_assert(!std::same_as<decltype(iter1), decltype(iter2)>);
// We cannot create a non-const iterator from a const iterator.
static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>);
@@ -108,7 +100,7 @@ test() {
auto iter1 = v.begin();
auto iter2 = std::as_const(v).begin();
- static_assert(!std::is_same_v<decltype(iter1), decltype(iter2)>);
+ static_assert(!std::same_as<decltype(iter1), decltype(iter2)>);
static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>);
static_assert(!std::constructible_from<decltype(iter2), decltype(iter1)>);
}
More information about the libcxx-commits
mailing list