[libcxx-commits] [libcxx] [libc++][ranges] LWG4013: Make lazy_split_view::outer-iterator::value_type non-default-constructible (PR #221919)

Vishank Singh via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 8 01:42:09 PDT 2026


https://github.com/VishankSingh updated https://github.com/llvm/llvm-project/pull/221919

>From effc8f3e44ddec946b130ebd5ae2f15166f4a97b Mon Sep 17 00:00:00 2001
From: vishanksingh <vishanksinghh at gmail.com>
Date: Tue, 8 Sep 2026 13:51:25 +0530
Subject: [PATCH] [libc++][ranges] LWG4013: Make
 lazy_split_view::outer-iterator::value_type non-default-constructible

Remove the public default constructor of outer-iterator::value_type and
make the remaining constructor private (exposition-only), as required by
LWG 4013.

Update the corresponding tests:
- ctor.default.pass.cpp now verifies the type is not default-constructible
- ctor.iter.pass.cpp verifies the constructor is private while still
  testing construction via operator*

Closes #105321
---
 libcxx/include/__ranges/lazy_split_view.h     |  4 ++--
 .../ctor.default.pass.cpp                     | 24 +++++++------------
 .../ctor.iter.pass.cpp                        |  9 +++++--
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index de7105944aa59..735cc0cfd63b7 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -193,12 +193,12 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
 
     struct value_type : view_interface<value_type> {
     private:
+      friend struct __outer_iterator;
       __outer_iterator __i_ = __outer_iterator();
 
-    public:
-      _LIBCPP_HIDE_FROM_ABI value_type() = default;
       _LIBCPP_HIDE_FROM_ABI constexpr explicit value_type(__outer_iterator __i) : __i_(std::move(__i)) {}
 
+    public:
       [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator<_Const> begin() const {
         return __inner_iterator<_Const>{__i_};
       }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.default.pass.cpp
index f92ea01ccd1db..d99857c48ab39 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.default.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.default.pass.cpp
@@ -8,28 +8,22 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// std::ranges::lazy_split_view::outer-iterator::value_type::value_type()
+// LWG 4013: lazy_split_view::outer-iterator::value_type should not provide a default constructor
 
+// class std::ranges::lazy_split_view::outer-iterator::value_type
+
+#include <concepts>
 #include <ranges>
+#include <type_traits>
 
 #include "../types.h"
 
 constexpr bool test() {
-  {
-    [[maybe_unused]] ValueTypeForward val;
-  }
-
-  {
-    [[maybe_unused]] ValueTypeForward val = {};
-  }
-
-  {
-    [[maybe_unused]] ValueTypeInput val;
-  }
+  static_assert(!std::default_initializable<ValueTypeForward>);
+  static_assert(!std::is_default_constructible_v<ValueTypeForward>);
 
-  {
-    [[maybe_unused]] ValueTypeInput val = {};
-  }
+  static_assert(!std::default_initializable<ValueTypeInput>);
+  static_assert(!std::is_default_constructible_v<ValueTypeInput>);
 
   return true;
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.iter.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.iter.pass.cpp
index f533c1b9fbebd..318a859ed2b37 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.iter.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/range.lazy.split.outer.value/ctor.iter.pass.cpp
@@ -9,12 +9,17 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
 // explicit outer-iterator::value_type::value_type(outer-iterator i)
+// LWG 4013: outer-iterator::value_type constructor taking outer-iterator should be private
 
 #include <ranges>
 
 #include <cassert>
 #include "../types.h"
 
+// Verify that the constructor is private / not constructible by users (LWG 4013).
+static_assert(!std::is_constructible_v<ValueTypeForward, OuterIterForward>);
+static_assert(!std::is_constructible_v<ValueTypeInput, OuterIterInput>);
+
 // Verify that the constructor is `explicit`.
 static_assert(!std::is_convertible_v<OuterIterForward, ValueTypeForward>);
 static_assert(!std::is_convertible_v<OuterIterInput, ValueTypeInput>);
@@ -24,7 +29,7 @@ constexpr bool test() {
   {
     CopyableView input = "a";
     SplitViewCopyable v(input, "b");
-    ValueTypeCopyable val(v.begin());
+    ValueTypeCopyable val = *v.begin();
     assert(val.begin().base() == input.begin());
   }
 
@@ -32,7 +37,7 @@ constexpr bool test() {
   {
     InputView input = "a";
     SplitViewInput v(input, 'b');
-    ValueTypeInput val(v.begin());
+    ValueTypeInput val = *v.begin();
     assert(*val.begin().base() == *input.begin());
   }
 



More information about the libcxx-commits mailing list