[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