[libcxx-commits] [libcxx] [libc++][ranges] Backport P2711R1: Making multi-param constructors of views ``explicit`` (PR #190513)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Apr 30 06:53:38 PDT 2026


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/190513

>From 6fa055955b7ca481db4c1b6cae5ff1e2f1c4f03f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 10:09:12 +0300
Subject: [PATCH 1/7] [libc++][ranges] Backport P2711R1: Making multi-param
 constructors of views explicit

As discussed in https://gcc.gnu.org/PR114298 - GCC and MSVC STL implemented P2711R1 as a DR. This PR proposes to do the same for libc++

# References:
- https://wg21.lin/p2711r1
- https://reviews.llvm.org/D144822
---
 libcxx/include/__config                   | 6 ------
 libcxx/include/__ranges/drop_view.h       | 2 +-
 libcxx/include/__ranges/drop_while_view.h | 2 +-
 libcxx/include/__ranges/filter_view.h     | 2 +-
 libcxx/include/__ranges/iota_view.h       | 8 ++++----
 libcxx/include/__ranges/lazy_split_view.h | 4 ++--
 libcxx/include/__ranges/split_view.h      | 4 ++--
 libcxx/include/__ranges/take_view.h       | 2 +-
 libcxx/include/__ranges/take_while_view.h | 2 +-
 libcxx/include/__ranges/transform_view.h  | 2 +-
 10 files changed, 14 insertions(+), 20 deletions(-)

diff --git a/libcxx/include/__config b/libcxx/include/__config
index 6cf9652327236..99bbb12b126c4 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -247,12 +247,6 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_EXPLICIT_SINCE_CXX14 explicit
 #  endif
 
-#  if _LIBCPP_STD_VER >= 23
-#    define _LIBCPP_EXPLICIT_SINCE_CXX23 explicit
-#  else
-#    define _LIBCPP_EXPLICIT_SINCE_CXX23
-#  endif
-
 #  if _LIBCPP_STD_VER >= 14
 #    define _LIBCPP_CONSTEXPR_SINCE_CXX14 constexpr
 #  else
diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
index feb3705d2df6c..ee68429216b37 100644
--- a/libcxx/include/__ranges/drop_view.h
+++ b/libcxx/include/__ranges/drop_view.h
@@ -74,7 +74,7 @@ class drop_view : public view_interface<drop_view<_View>> {
     requires default_initializable<_View>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit
   drop_view(_View __base, range_difference_t<_View> __count)
       : __count_(__count), __base_(std::move(__base)) {
     _LIBCPP_ASSERT_UNCATEGORIZED(__count_ >= 0, "count must be greater than or equal to zero.");
diff --git a/libcxx/include/__ranges/drop_while_view.h b/libcxx/include/__ranges/drop_while_view.h
index 1fe4e17f8048b..ed5b91d99425f 100644
--- a/libcxx/include/__ranges/drop_while_view.h
+++ b/libcxx/include/__ranges/drop_while_view.h
@@ -54,7 +54,7 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS drop_while_view : public view_interfa
     requires default_initializable<_View> && default_initializable<_Pred>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_while_view(_View __base, _Pred __pred)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit drop_while_view(_View __base, _Pred __pred)
       : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {}
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h
index 3ad69ea100931..4612dc4a9ba1d 100644
--- a/libcxx/include/__ranges/filter_view.h
+++ b/libcxx/include/__ranges/filter_view.h
@@ -72,7 +72,7 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS filter_view : public view_interface<f
     requires default_initializable<_View> && default_initializable<_Pred>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 filter_view(_View __base, _Pred __pred)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit filter_view(_View __base, _Pred __pred)
       : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) {}
 
   template <class _Vp = _View>
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 29f96545ab34f..fe820ccfb172d 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -316,7 +316,7 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit
   iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)
       : __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) {
     // Validate the precondition if possible.
@@ -326,15 +326,15 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
     }
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(__iterator __first, __iterator __last)
     requires same_as<_Start, _BoundSentinel>
       : iota_view(std::move(__first.__value_), std::move(__last.__value_)) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(__iterator __first, _BoundSentinel __last)
     requires same_as<_BoundSentinel, unreachable_sentinel_t>
       : iota_view(std::move(__first.__value_), std::move(__last)) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(__iterator __first, __sentinel __last)
     requires(!same_as<_Start, _BoundSentinel> && !same_as<_BoundSentinel, unreachable_sentinel_t>)
       : iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {}
 
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index cca9191d26818..938dca24cc4fc 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -86,13 +86,13 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
     requires default_initializable<_View> && default_initializable<_Pattern>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_View __base, _Pattern __pattern)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit lazy_split_view(_View __base, _Pattern __pattern)
       : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {}
 
   template <input_range _Range>
     requires constructible_from<_View, views::all_t<_Range>> &&
                  constructible_from<_Pattern, single_view<range_value_t<_Range>>>
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
       : __base_(views::all(std::forward<_Range>(__r))), __pattern_(views::single(std::move(__e))) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h
index 2ec908ba4070e..ed323b0014da9 100644
--- a/libcxx/include/__ranges/split_view.h
+++ b/libcxx/include/__ranges/split_view.h
@@ -78,13 +78,13 @@ class split_view : public view_interface<split_view<_View, _Pattern>> {
     requires default_initializable<_View> && default_initializable<_Pattern>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 split_view(_View __base, _Pattern __pattern)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit split_view(_View __base, _Pattern __pattern)
       : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {}
 
   template <forward_range _Range>
     requires constructible_from<_View, views::all_t<_Range>> &&
                  constructible_from<_Pattern, single_view<range_value_t<_Range>>>
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit
   split_view(_Range&& __range, range_value_t<_Range> __elem)
       : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {}
 
diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h
index 13cb4a285d9df..927f56d7eeb64 100644
--- a/libcxx/include/__ranges/take_view.h
+++ b/libcxx/include/__ranges/take_view.h
@@ -69,7 +69,7 @@ class take_view : public view_interface<take_view<_View>> {
     requires default_initializable<_View>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit
   take_view(_View __base, range_difference_t<_View> __count)
       : __base_(std::move(__base)), __count_(__count) {
     _LIBCPP_ASSERT_UNCATEGORIZED(__count >= 0, "count has to be greater than or equal to zero");
diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h
index 4977f139fc555..955f681ef76ed 100644
--- a/libcxx/include/__ranges/take_while_view.h
+++ b/libcxx/include/__ranges/take_while_view.h
@@ -58,7 +58,7 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS take_while_view : public view_interfa
     requires default_initializable<_View> && default_initializable<_Pred>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit take_while_view(_View __base, _Pred __pred)
       : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index ab1adf9cdbe68..9fec673b4b656 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -85,7 +85,7 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS transform_view : public view_interfac
     requires default_initializable<_View> && default_initializable<_Fn>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 transform_view(_View __base, _Fn __func)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit transform_view(_View __base, _Fn __func)
       : __func_(std::in_place, std::move(__func)), __base_(std::move(__base)) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&

>From 5eedcf93c38025bd6cfb44dbfd3a8ec0ce3af60c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 12:09:14 +0300
Subject: [PATCH 2/7] Update tests

---
 .../range.drop.while/ctor.view.pass.cpp       |  9 --------
 .../range.drop/ctor.view.pass.cpp             |  9 --------
 .../range.filter/ctor.view_pred.pass.cpp      |  2 --
 .../range.lazy.split/ctor.range.pass.cpp      |  7 ------
 .../range.lazy.split/ctor.view.pass.cpp       |  2 --
 .../range.split/ctor.range.pass.cpp           | 10 ---------
 .../range.split/ctor.view.pass.cpp            |  9 --------
 .../range.take.while/ctor.view.pass.cpp       |  9 --------
 .../range.take/ctor.view_count.pass.cpp       |  9 --------
 .../ctor.view_function.pass.cpp               |  9 --------
 .../range.iota.view/ctor.first.last.pass.cpp  | 22 -------------------
 .../range.iota.view/ctor.value.bound.pass.cpp | 21 ------------------
 12 files changed, 118 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
index 326cabd637089..dcc31bd7c2a65 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
@@ -36,18 +36,9 @@ struct Pred {
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::drop_while_view<View, Pred>, View, Pred>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert( test_convertible<std::ranges::drop_while_view<View, Pred>, View, Pred>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     std::ranges::drop_while_view<View, Pred> dwv{View{{}, MoveOnly{5}}, Pred{}};
diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
index aeb31ae2fec4b..43d04c75c70b1 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
@@ -19,18 +19,9 @@
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::drop_view<View>, View, std::ranges::range_difference_t<View>>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::drop_view<View>, View, std::ranges::range_difference_t<View>>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   std::ranges::drop_view dropView1(MoveOnlyView(), 4);
   assert(dropView1.size() == 4);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
index 8eaf6eba35709..3e75791568ec8 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
@@ -45,8 +45,6 @@ struct TrackingRange : TrackInitialization, std::ranges::view_base {
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::filter_view<Range, Pred>, Range, Pred>(),
               "This constructor must be explicit");
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
index 8eeaa3dae36db..3097e6db0f009 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
@@ -88,19 +88,12 @@ static_assert(std::is_copy_constructible_v<StrView>);
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
 
 static_assert(
     !test_convertible<std::ranges::lazy_split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
     "This constructor must be explicit");
 
-#else
 
-static_assert(
-    test_convertible<std::ranges::lazy_split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
-    "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
 
 constexpr bool test() {
   {
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
index 46af5498d59a0..0f40b24d07920 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
@@ -48,8 +48,6 @@ using Pattern = ViewWithCounting;
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::lazy_split_view<View, Pattern>, View, Pattern>(),
               "This constructor must be explicit");
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
index bbe08befdb419..7a27a9548c229 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
@@ -73,20 +73,10 @@ static_assert(std::is_copy_constructible_v<StrView>);
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(
     !test_convertible<std::ranges::split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
     "This constructor must be explicit");
 
-# else
-
-static_assert(
-    test_convertible<std::ranges::split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
-    "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     using V = std::ranges::split_view<StrView, StrView>;
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
index 27fc4b84c5206..7826d8969b97d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
@@ -46,18 +46,9 @@ using Pattern = ViewWithCounting;
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert( test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     std::string_view input = "abc def";
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
index 469b2698c8844..28cef83a6cf72 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
@@ -36,18 +36,9 @@ struct Pred {
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::take_while_view<View, Pred>, View, Pred>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::take_while_view<View, Pred>, View, Pred>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     std::ranges::take_while_view<View, Pred> twv{View{{}, MoveOnly{5}}, Pred{}};
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
index f37ffb0825ac1..fdc4bb4b23261 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
@@ -21,18 +21,9 @@
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::take_view<View>, View, std::ranges::range_difference_t<View>>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::take_view<View>, View, std::ranges::range_difference_t<View>>(),
-              "This constructor must be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
index 63a43d189256f..5593b778467f6 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
@@ -32,18 +32,9 @@ struct F {
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::transform_view<Range, F>, Range, F>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert( test_convertible<std::ranges::transform_view<Range, F>, Range, F>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
 
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
index 67b7dc428a14f..2f61591e11677 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
@@ -19,8 +19,6 @@
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 std::ranges::iota_view<SomeInt, SomeInt> view;
 
 static_assert(!test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
@@ -38,25 +36,6 @@ static_assert(!test_convertible<std::ranges::iota_view<SomeInt, IntComparableWit
                                 decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
-                               decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
-                               decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
-              "This constructor must not be explicit");
-
-static_assert(test_convertible<std::ranges::iota_view<SomeInt>,
-                               decltype(std::ranges::iota_view{SomeInt{0}}.begin()),
-                               decltype(std::unreachable_sentinel)>(),
-              "This constructor must not be explicit");
-
-static_assert(test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
-                               decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
-                               decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     std::ranges::iota_view commonView(SomeInt(0), SomeInt(10));
@@ -91,4 +70,3 @@ int main(int, char**) {
 
   return 0;
 }
-
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
index 7528e1ccf3ee0..7aa65e58fb6cc 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
@@ -24,8 +24,6 @@ TEST_MSVC_DIAGNOSTIC_IGNORED(4018 4389) // various "signed/unsigned mismatch"
 
 // SFINAE tests.
 
-#if TEST_STD_VER >= 23
-
 static_assert(!test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
                                 decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
                                 decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
@@ -41,25 +39,6 @@ static_assert(!test_convertible<std::ranges::iota_view<SomeInt, IntComparableWit
                                 decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert( test_convertible<std::ranges::iota_view<SomeInt, SomeInt>,
-                                decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.begin()),
-                                decltype(std::ranges::iota_view<SomeInt, SomeInt>{}.end())>(),
-              "This constructor must not be explicit");
-
-static_assert( test_convertible<std::ranges::iota_view<SomeInt>,
-                                decltype(std::ranges::iota_view<SomeInt>{}.begin()),
-                                decltype(std::unreachable_sentinel)>(),
-              "This constructor must not be explicit");
-
-static_assert( test_convertible<std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>>,
-                                decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.begin()),
-                                decltype(std::ranges::iota_view{SomeInt(0), IntComparableWith(SomeInt(10))}.end())>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   {
     std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(0), SomeInt(10));

>From 11ee2c14964396b547bae46a4a0114ed82c1ea5f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 12:45:20 +0300
Subject: [PATCH 3/7] Fixed formatting errors

---
 libcxx/include/__ranges/drop_view.h               | 15 +++++++--------
 libcxx/include/__ranges/iota_view.h               |  4 ++--
 libcxx/include/__ranges/lazy_split_view.h         |  8 ++++----
 libcxx/include/__ranges/split_view.h              |  3 +--
 libcxx/include/__ranges/take_view.h               |  3 +--
 .../range.lazy.split/ctor.range.pass.cpp          |  3 ---
 6 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
index ee68429216b37..9d2946e7e6bc9 100644
--- a/libcxx/include/__ranges/drop_view.h
+++ b/libcxx/include/__ranges/drop_view.h
@@ -74,8 +74,7 @@ class drop_view : public view_interface<drop_view<_View>> {
     requires default_initializable<_View>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit
-  drop_view(_View __base, range_difference_t<_View> __count)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit drop_view(_View __base, range_difference_t<_View> __count)
       : __count_(__count), __base_(std::move(__base)) {
     _LIBCPP_ASSERT_UNCATEGORIZED(__count_ >= 0, "count must be greater than or equal to zero.");
   }
@@ -289,14 +288,14 @@ struct __fn {
   template <class _Range, convertible_to<range_difference_t<_Range>> _Np, class _RawRange = remove_cvref_t<_Range>>
   // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other
   // overloads.
-    requires(!(__is_empty_view<_RawRange> ||
+    requires(
+        !(__is_empty_view<_RawRange> ||
 #  if _LIBCPP_STD_VER >= 23
-               __is_repeat_specialization<_RawRange> ||
+          __is_repeat_specialization<_RawRange> ||
 #  endif
-               (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> &&
-                random_access_range<_RawRange>) ||
-               (__is_passthrough_specialization<_RawRange> && sized_range<_RawRange> &&
-                random_access_range<_RawRange>)))
+          (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> &&
+           random_access_range<_RawRange>) ||
+          (__is_passthrough_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>)))
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const
       noexcept(noexcept(drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n))))
           -> decltype(drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n))) {
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index fe820ccfb172d..38e0ccaf2849e 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -316,8 +316,8 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit
-  iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(type_identity_t<_Start> __value,
+                                                     type_identity_t<_BoundSentinel> __bound_sentinel)
       : __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) {
     // Validate the precondition if possible.
     if constexpr (totally_ordered_with<_Start, _BoundSentinel>) {
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index 938dca24cc4fc..b6ea515f1c70d 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -104,7 +104,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
 
   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
     if constexpr (forward_range<_View>) {
-      return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::begin(__base_)};
+      return __outer_iterator< __simple_view<_View> && __simple_view< _Pattern >>{*this, ranges::begin(__base_)};
     } else {
       __current_.__emplace(ranges::begin(__base_));
       return __outer_iterator<false>{*this};
@@ -120,7 +120,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
   _LIBCPP_HIDE_FROM_ABI constexpr auto end()
     requires forward_range<_View> && common_range<_View>
   {
-    return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::end(__base_)};
+    return __outer_iterator< __simple_view<_View> && __simple_view< _Pattern >>{*this, ranges::end(__base_)};
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
@@ -404,8 +404,8 @@ template <class _Range, class _Pattern>
 lazy_split_view(_Range&&, _Pattern&&) -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>;
 
 template <input_range _Range>
-lazy_split_view(_Range&&,
-                range_value_t<_Range>) -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
+lazy_split_view(_Range&&, range_value_t<_Range>)
+    -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
 
 namespace views {
 namespace __lazy_split_view {
diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h
index ed323b0014da9..17a2ceeca6686 100644
--- a/libcxx/include/__ranges/split_view.h
+++ b/libcxx/include/__ranges/split_view.h
@@ -84,8 +84,7 @@ class split_view : public view_interface<split_view<_View, _Pattern>> {
   template <forward_range _Range>
     requires constructible_from<_View, views::all_t<_Range>> &&
                  constructible_from<_Pattern, single_view<range_value_t<_Range>>>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit
-  split_view(_Range&& __range, range_value_t<_Range> __elem)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit split_view(_Range&& __range, range_value_t<_Range> __elem)
       : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h
index 927f56d7eeb64..999f686537f2c 100644
--- a/libcxx/include/__ranges/take_view.h
+++ b/libcxx/include/__ranges/take_view.h
@@ -69,8 +69,7 @@ class take_view : public view_interface<take_view<_View>> {
     requires default_initializable<_View>
   = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit
-  take_view(_View __base, range_difference_t<_View> __count)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit take_view(_View __base, range_difference_t<_View> __count)
       : __base_(std::move(__base)), __count_(__count) {
     _LIBCPP_ASSERT_UNCATEGORIZED(__count >= 0, "count has to be greater than or equal to zero");
   }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
index 3097e6db0f009..2eb272ee70f90 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
@@ -88,13 +88,10 @@ static_assert(std::is_copy_constructible_v<StrView>);
 
 // SFINAE tests.
 
-
 static_assert(
     !test_convertible<std::ranges::lazy_split_view<StrView, StrView>, StrView, std::ranges::range_value_t<StrView>>(),
     "This constructor must be explicit");
 
-
-
 constexpr bool test() {
   {
     using V = std::ranges::lazy_split_view<StrView, StrView>;

>From b98c609607ca5d2f0040d9ef889bbbb72cb64c40 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 17:21:46 +0300
Subject: [PATCH 4/7] Fix tests

---
 libcxx/docs/Status/Cxx23Papers.csv                         | 2 +-
 .../range.adaptors/range.filter/ctor.view_pred.pass.cpp    | 7 -------
 .../range.adaptors/range.lazy.split/ctor.view.pass.cpp     | 7 -------
 3 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 41b1b8f884eff..4a79549a6ae4f 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -105,7 +105,7 @@
 "`P0290R4 <https://wg21.link/P0290R4>`__","``apply()`` for ``synchronized_value<T>``","2023-02 (Issaquah)","","","`#105249 <https://github.com/llvm/llvm-project/issues/105249>`__",""
 "`P2770R0 <https://wg21.link/P2770R0>`__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Complete|","21","`#105250 <https://github.com/llvm/llvm-project/issues/105250>`__",""
 "`P2164R9 <https://wg21.link/P2164R9>`__","``views::enumerate``","2023-02 (Issaquah)","|Complete|","23","`#105251 <https://github.com/llvm/llvm-project/issues/105251>`__",""
-"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|Complete|","21","`#105252 <https://github.com/llvm/llvm-project/issues/105252>`__",""
+"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|Complete|","21","`#105252 <https://github.com/llvm/llvm-project/issues/105252>`__","Implemented as a DR in C++20."
 "`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete|","20","`#105253 <https://github.com/llvm/llvm-project/issues/105253>`__","Implemented as a DR in C++20. Other implementations will do the same."
 "`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19","`#105254 <https://github.com/llvm/llvm-project/issues/105254>`__",""
 "`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17","`#105255 <https://github.com/llvm/llvm-project/issues/105255>`__",""
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
index 3e75791568ec8..00a4caf248786 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
@@ -48,13 +48,6 @@ struct TrackingRange : TrackInitialization, std::ranges::view_base {
 static_assert(!test_convertible<std::ranges::filter_view<Range, Pred>, Range, Pred>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::filter_view<Range, Pred>, Range, Pred>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
index 0f40b24d07920..58a966d78e1c7 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
@@ -51,13 +51,6 @@ using Pattern = ViewWithCounting;
 static_assert(!test_convertible<std::ranges::lazy_split_view<View, Pattern>, View, Pattern>(),
               "This constructor must be explicit");
 
-#else
-
-static_assert(test_convertible<std::ranges::lazy_split_view<View, Pattern>, View, Pattern>(),
-              "This constructor must not be explicit");
-
-#endif // TEST_STD_VER >= 23
-
 constexpr bool test() {
   // Calling the constructor with `(ForwardView, ForwardView)`.
   {

>From 6f496a8c0c6f635f3eba0ad699fef0b322284348 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 17:29:31 +0300
Subject: [PATCH 5/7] Reverted unrelated formatting changes

---
 libcxx/include/__ranges/drop_view.h       | 12 ++++++------
 libcxx/include/__ranges/lazy_split_view.h |  8 ++++----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
index 9d2946e7e6bc9..e3754e64d536f 100644
--- a/libcxx/include/__ranges/drop_view.h
+++ b/libcxx/include/__ranges/drop_view.h
@@ -288,14 +288,14 @@ struct __fn {
   template <class _Range, convertible_to<range_difference_t<_Range>> _Np, class _RawRange = remove_cvref_t<_Range>>
   // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other
   // overloads.
-    requires(
-        !(__is_empty_view<_RawRange> ||
+    requires(!(__is_empty_view<_RawRange> ||
 #  if _LIBCPP_STD_VER >= 23
-          __is_repeat_specialization<_RawRange> ||
+               __is_repeat_specialization<_RawRange> ||
 #  endif
-          (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> &&
-           random_access_range<_RawRange>) ||
-          (__is_passthrough_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>)))
+               (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> &&
+                random_access_range<_RawRange>) ||
+               (__is_passthrough_specialization<_RawRange> && sized_range<_RawRange> &&
+                random_access_range<_RawRange>)))
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const
       noexcept(noexcept(drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n))))
           -> decltype(drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n))) {
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index b6ea515f1c70d..938dca24cc4fc 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -104,7 +104,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
 
   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
     if constexpr (forward_range<_View>) {
-      return __outer_iterator< __simple_view<_View> && __simple_view< _Pattern >>{*this, ranges::begin(__base_)};
+      return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::begin(__base_)};
     } else {
       __current_.__emplace(ranges::begin(__base_));
       return __outer_iterator<false>{*this};
@@ -120,7 +120,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
   _LIBCPP_HIDE_FROM_ABI constexpr auto end()
     requires forward_range<_View> && common_range<_View>
   {
-    return __outer_iterator< __simple_view<_View> && __simple_view< _Pattern >>{*this, ranges::end(__base_)};
+    return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::end(__base_)};
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
@@ -404,8 +404,8 @@ template <class _Range, class _Pattern>
 lazy_split_view(_Range&&, _Pattern&&) -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>;
 
 template <input_range _Range>
-lazy_split_view(_Range&&, range_value_t<_Range>)
-    -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
+lazy_split_view(_Range&&,
+                range_value_t<_Range>) -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
 
 namespace views {
 namespace __lazy_split_view {

>From 99416ed2bf7da930ac3e5a49111d09078d4c9c0c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 5 Apr 2026 17:37:30 +0300
Subject: [PATCH 6/7] Updated tests

---
 .../ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp   | 2 +-
 .../std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp     | 2 +-
 .../ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp  | 2 +-
 .../ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp  | 2 +-
 .../ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp   | 2 +-
 .../std/ranges/range.adaptors/range.split/ctor.range.pass.cpp   | 2 +-
 .../std/ranges/range.adaptors/range.split/ctor.view.pass.cpp    | 2 +-
 .../ranges/range.adaptors/range.take.while/ctor.view.pass.cpp   | 2 +-
 .../ranges/range.adaptors/range.take/ctor.view_count.pass.cpp   | 2 +-
 .../range.adaptors/range.transform/ctor.view_function.pass.cpp  | 2 +-
 .../range.factories/range.iota.view/ctor.first.last.pass.cpp    | 2 +-
 .../range.factories/range.iota.view/ctor.value.bound.pass.cpp   | 2 +-
 12 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
index dcc31bd7c2a65..1f38f113545cf 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop.while/ctor.view.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr drop_while_view(V base, Pred pred); // explicit since C++23
+// constexpr explicit drop_while_view(V base, Pred pred); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
index 43d04c75c70b1..b036b34c25a72 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.drop/ctor.view.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr drop_view(V base, range_difference_t<V> count);  // explicit since C++23
+// constexpr explicit drop_view(V base, range_difference_t<V> count);  // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
index 00a4caf248786..dafddfe3d8789 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr filter_view(View, Pred); // explicit since C++23
+// constexpr explicit filter_view(View, Pred); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
index 2eb272ee70f90..cc06e260c221a 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
@@ -11,7 +11,7 @@
 // template <input_range Range>
 //   requires constructible_from<View, views::all_t<Range>> &&
 //             constructible_from<Pattern, single_view<range_value_t<Range>>>
-// constexpr lazy_split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
+// constexpr explicit lazy_split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
 
 #include <ranges>
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
index 58a966d78e1c7..efb5965ff386d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.view.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr lazy_split_view(View base, Pattern pattern); // explicit since C++23
+// constexpr explicit lazy_split_view(View base, Pattern pattern); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
index 7a27a9548c229..4e2f7c8890e82 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.range.pass.cpp
@@ -11,7 +11,7 @@
 // template <input_range Range>
 //   requires constructible_from<View, views::all_t<Range>> &&
 //             constructible_from<Pattern, single_view<range_value_t<Range>>>
-// constexpr split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
+// constexpr explicit split_view(Range&& r, range_value_t<Range> e); // explicit since C++23
 
 #include <algorithm>
 #include <cassert>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
index 7826d8969b97d..f68dda1e8ff48 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/ctor.view.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr split_view(View base, Pattern pattern); // explicit since C++23
+// constexpr explicit split_view(View base, Pattern pattern); // explicit since C++23
 
 #include <algorithm>
 #include <cassert>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
index 28cef83a6cf72..4d68bc9580dfe 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take.while/ctor.view.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr take_while_view(V base, Pred pred); // explicit since C++23
+// constexpr explicit take_while_view(V base, Pred pred); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
index fdc4bb4b23261..e1ddf40febb2a 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.take/ctor.view_count.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr take_view(V base, range_difference_t<V> count); // explicit since C++23
+// constexpr explicit take_view(V base, range_difference_t<V> count); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
index 5593b778467f6..afe1faf7f3cdb 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/ctor.view_function.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr transform_view(View, F); // explicit since C++23
+// constexpr explicit transform_view(View, F); // explicit since C++23
 
 #include <cassert>
 #include <ranges>
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
index 2f61591e11677..25a78d0475f7e 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// constexpr iota_view(iterator first, see below last); // explicit since C++23
+// constexpr explicit iota_view(iterator first, see below last); // explicit since C++23
 
 #include <ranges>
 #include <cassert>
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
index 7aa65e58fb6cc..b6f4295498644 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp
@@ -14,7 +14,7 @@ TEST_CLANG_DIAGNOSTIC_IGNORED("-Wsign-compare")
 TEST_GCC_DIAGNOSTIC_IGNORED("-Wsign-compare")
 TEST_MSVC_DIAGNOSTIC_IGNORED(4018 4389) // various "signed/unsigned mismatch"
 
-// constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); // explicit since C++23
+// constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); // explicit since C++23
 
 #include <ranges>
 #include <cassert>

>From c27e60ac016ebc115ec572c3a14fb579a76a8e0b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hristo.goshev.hristov at gmail.com>
Date: Sun, 5 Apr 2026 17:48:24 +0300
Subject: [PATCH 7/7] Update libcxx/docs/Status/Cxx23Papers.csv

Co-authored-by: A. Jiang <de34 at live.cn>
---
 libcxx/docs/Status/Cxx23Papers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 4a79549a6ae4f..82038e61a259a 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -105,7 +105,7 @@
 "`P0290R4 <https://wg21.link/P0290R4>`__","``apply()`` for ``synchronized_value<T>``","2023-02 (Issaquah)","","","`#105249 <https://github.com/llvm/llvm-project/issues/105249>`__",""
 "`P2770R0 <https://wg21.link/P2770R0>`__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Complete|","21","`#105250 <https://github.com/llvm/llvm-project/issues/105250>`__",""
 "`P2164R9 <https://wg21.link/P2164R9>`__","``views::enumerate``","2023-02 (Issaquah)","|Complete|","23","`#105251 <https://github.com/llvm/llvm-project/issues/105251>`__",""
-"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|Complete|","21","`#105252 <https://github.com/llvm/llvm-project/issues/105252>`__","Implemented as a DR in C++20."
+"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|Complete|","21","`#105252 <https://github.com/llvm/llvm-project/issues/105252>`__","Implemented as a DR in C++20 since LLVM 23."
 "`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete|","20","`#105253 <https://github.com/llvm/llvm-project/issues/105253>`__","Implemented as a DR in C++20. Other implementations will do the same."
 "`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19","`#105254 <https://github.com/llvm/llvm-project/issues/105254>`__",""
 "`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17","`#105255 <https://github.com/llvm/llvm-project/issues/105255>`__",""



More information about the libcxx-commits mailing list