[libcxx-commits] [libcxx] [libc++][ranges] Implement LWG 3599 (PR #221573)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Sep 6 07:17:21 PDT 2026
https://github.com/jiang1997 created https://github.com/llvm/llvm-project/pull/221573
Implement [LWG 3599](https://wg21.link/LWG3599) by requiring `forward_range<const Pattern>` for the `const` overloads of `lazy_split_view::begin` and `end`.
This adds tests for disabled `begin()` and fallback `end()` on non-const-forward patterns, as well as a regression test for `view_interface::front()`.
Closes #189808
>From 8d6a1adbf894a5b03cfaf580440e384b223373b8 Mon Sep 17 00:00:00 2001
From: jiang1997 <jieke at live.cn>
Date: Sun, 6 Sep 2026 20:43:47 +0800
Subject: [PATCH] [libc++][ranges] Implement LWG 3599
---
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
libcxx/include/__ranges/lazy_split_view.h | 5 +++--
.../range.lazy.split/begin.pass.cpp | 18 ++++++++----------
.../range.lazy.split/end.pass.cpp | 13 +++++++++++++
.../range.lazy.split/view_interface.pass.cpp | 5 +++++
5 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index cf30ba8a45ca5..e46a043477527 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -263,7 +263,7 @@
"`LWG2414 <https://wg21.link/LWG2414>`__","Member function reentrancy should be implementation-defined","2026-03 (Croydon)","","","`#189805 <https://github.com/llvm/llvm-project/issues/189805>`__",""
"`LWG2746 <https://wg21.link/LWG2746>`__","Inconsistency between requirements for ``emplace`` between ``optional`` and ``variant``","2026-03 (Croydon)","","","`#189806 <https://github.com/llvm/llvm-project/issues/189806>`__",""
"`LWG3504 <https://wg21.link/LWG3504>`__","``condition_variable::wait_for`` is overspecified","2026-03 (Croydon)","","","`#189807 <https://github.com/llvm/llvm-project/issues/189807>`__",""
-"`LWG3599 <https://wg21.link/LWG3599>`__","The ``const`` overload of ``lazy_split_view::begin`` should be constrained by ``const Pattern``","2026-03 (Croydon)","","","`#189808 <https://github.com/llvm/llvm-project/issues/189808>`__",""
+"`LWG3599 <https://wg21.link/LWG3599>`__","The ``const`` overload of ``lazy_split_view::begin`` should be constrained by ``const Pattern``","2026-03 (Croydon)","|Complete|","24","`#189808 <https://github.com/llvm/llvm-project/issues/189808>`__",""
"`LWG3662 <https://wg21.link/LWG3662>`__","``basic_string::append/assign(NTBS, pos, n)`` suboptimal","2026-03 (Croydon)","|Complete|","23","`#189809 <https://github.com/llvm/llvm-project/issues/189809>`__",""
"`LWG3777 <https://wg21.link/LWG3777>`__","Common ``cartesian_product_view`` produces an invalid range if the first range is input and one of the ranges is empty","2026-03 (Croydon)","","","`#189810 <https://github.com/llvm/llvm-project/issues/189810>`__",""
"`LWG3797 <https://wg21.link/LWG3797>`__","``elements_view`` insufficiently constrained","2026-03 (Croydon)","","","`#189811 <https://github.com/llvm/llvm-project/issues/189811>`__",""
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index 9c44d26faf1e7..de7105944aa59 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -112,7 +112,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
- requires forward_range<_View> && forward_range<const _View>
+ requires forward_range<_View> && forward_range<const _View> && forward_range<const _Pattern>
{
return __outer_iterator<true>{*this, ranges::begin(__base_)};
}
@@ -124,7 +124,8 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
- if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View>) {
+ if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View> &&
+ forward_range<const _Pattern>) {
return __outer_iterator<true>{*this, ranges::end(__base_)};
} else {
return default_sentinel;
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/begin.pass.cpp
index 113272703d59f..5d166697a7124 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/begin.pass.cpp
@@ -9,7 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// constexpr auto begin();
-// constexpr auto begin() const requires forward_range<View> && forward_range<const View>;
+// constexpr auto begin() const
+// requires forward_range<View> && forward_range<const View> && forward_range<const Pattern>;
#include <ranges>
@@ -26,7 +27,8 @@ concept ConstBeginDisabled = !requires (const View v) {
constexpr bool test() {
// non-const: forward_range<View> && simple-view<View> -> outer-iterator<Const = true>
- // const: forward_range<View> && forward_range<const View> -> outer-iterator<Const = true>
+ // const: forward_range<View> && forward_range<const View> && forward_range<const Pattern>
+ // -> outer-iterator<Const = true>
{
using V = ForwardView;
using P = V;
@@ -52,7 +54,8 @@ constexpr bool test() {
}
// non-const: forward_range<View> && !simple-view<View> -> outer-iterator<Const = false>
- // const: forward_range<View> && forward_range<const View> -> outer-iterator<Const = true>
+ // const: forward_range<View> && forward_range<const View> && forward_range<const Pattern>
+ // -> outer-iterator<Const = true>
{
using V = ForwardDiffView;
using P = V;
@@ -96,7 +99,7 @@ constexpr bool test() {
}
// non-const: forward_range<View> && simple-view<View> && !simple-view<Pattern> -> outer-iterator<Const = false>
- // const: forward_range<View> && forward_range<const View> -> outer-iterator<Const = true>
+ // const: forward_range<View> && forward_range<const View> && !forward_range<const Pattern> -> disabled
{
using V = ForwardView;
using P = ForwardOnlyIfNonConstView;
@@ -113,12 +116,7 @@ constexpr bool test() {
static_assert(std::is_same_v<decltype(*(*it).begin()), const char&>);
}
- {
- const std::ranges::lazy_split_view<V, P> cv;
- auto it = cv.begin();
- static_assert(std::is_same_v<decltype(it)::iterator_concept, std::forward_iterator_tag>);
- static_assert(std::is_same_v<decltype(*(*it).begin()), const char&>);
- }
+ static_assert(ConstBeginDisabled<std::ranges::lazy_split_view<V, P>>);
}
// non-const: !forward_range<View> && tiny-range<Pattern> -> outer-iterator<Const = false>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
index 3e3facc1cbe3d..5ce2bce9f00f2 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
@@ -156,6 +156,19 @@ constexpr bool test() {
}
}
+ // const: !forward_range<const P> -> default_sentinel
+ {
+ using V = ForwardView;
+ using P = ForwardOnlyIfNonConstView;
+
+ static_assert(std::ranges::forward_range<const V>);
+ static_assert(std::ranges::common_range<const V>);
+ static_assert(!std::ranges::forward_range<const P>);
+
+ const std::ranges::lazy_split_view<V, P> cv;
+ static_assert(std::same_as<decltype(cv.end()), std::default_sentinel_t>);
+ }
+
return true;
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/view_interface.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/view_interface.pass.cpp
index 8d5982d59759d..4d6c21c062233 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/view_interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/view_interface.pass.cpp
@@ -60,6 +60,11 @@ constexpr bool test() {
SplitViewForward v("abc", "");
assert(*(v.front()).begin() == 'a');
}
+ {
+ auto pattern = std::views::iota(0) | std::views::take(1) | std::views::reverse;
+ auto v = std::views::single(42) | std::views::lazy_split(pattern);
+ assert(*v.front().begin() == 42);
+ }
return true;
}
More information about the libcxx-commits
mailing list