[libcxx-commits] [libcxx] [libc++] LWG4012: common_view::begin/end are missing the simple-view check (PR #153674)
Nhat Nguyen via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 18 12:55:07 PDT 2025
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/153674
>From 06a6c6168ca510ed773346f57693a2b273451208 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Thu, 14 Aug 2025 16:35:58 -0400
Subject: [PATCH 1/3] initial commit
---
libcxx/include/__ranges/common_view.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h
index 133236dd1d78a..ff26a78c00052 100644
--- a/libcxx/include/__ranges/common_view.h
+++ b/libcxx/include/__ranges/common_view.h
@@ -58,7 +58,7 @@ class common_view : public view_interface<common_view<_View>> {
_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto begin() requires (!__simple_view<_View>) {
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_);
else
@@ -74,7 +74,7 @@ class common_view : public view_interface<common_view<_View>> {
return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end() requires (!__simple_view<_View>) {
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_) + ranges::size(__base_);
else
>From 31d0cefaf9ffe931a58d7cabd4afbb1fe7e287bf Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Thu, 14 Aug 2025 16:43:57 -0400
Subject: [PATCH 2/3] clang format
---
libcxx/include/__ranges/common_view.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h
index ff26a78c00052..54bb8039b48af 100644
--- a/libcxx/include/__ranges/common_view.h
+++ b/libcxx/include/__ranges/common_view.h
@@ -58,7 +58,9 @@ class common_view : public view_interface<common_view<_View>> {
_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() requires (!__simple_view<_View>) {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+ requires(!__simple_view<_View>)
+ {
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_);
else
@@ -74,7 +76,9 @@ class common_view : public view_interface<common_view<_View>> {
return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() requires (!__simple_view<_View>) {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ requires(!__simple_view<_View>)
+ {
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_) + ranges::size(__base_);
else
>From 265621cf45d58a768b83130da2fd2c071a5f21c3 Mon Sep 17 00:00:00 2001
From: changkhothuychung <nhat7203 at gmail.com>
Date: Mon, 18 Aug 2025 15:54:31 -0400
Subject: [PATCH 3/3] sfinae test
---
.../range.common.view/begin.pass.cpp | 31 ++++++++++++++++---
.../range.common.view/end.pass.cpp | 7 +++++
.../range.adaptors/range.common.view/types.h | 13 ++++++++
3 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp
index 96116dc37553a..ab74e1efb930f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/begin.pass.cpp
@@ -25,16 +25,30 @@ struct MutableView : std::ranges::view_base {
sentinel_wrapper<int*> end();
};
-template<class View>
-concept BeginEnabled = requires(View v) { v.begin(); };
+template <class T>
+concept HasConstBegin = requires(const T& ct) { ct.begin(); };
+
+template <class T>
+concept HasBegin = requires(T& t) { t.begin(); };
+
+template <class T>
+concept HasConstAndNonConstBegin = HasConstBegin<T> && requires(T& t, const T& ct) {
+ requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>;
+};
+
+template <class T>
+concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;
+
+template <class T>
+concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;
constexpr bool test() {
int buf[8] = {1, 2, 3, 4, 5, 6, 7, 8};
{
- static_assert( BeginEnabled<std::ranges::common_view<CopyableView> const&>);
- static_assert( BeginEnabled<std::ranges::common_view<MutableView>&>);
- static_assert(!BeginEnabled<std::ranges::common_view<MutableView> const&>);
+ static_assert( HasBegin<std::ranges::common_view<CopyableView> const&>);
+ static_assert( HasBegin<std::ranges::common_view<MutableView>&>);
+ static_assert(!HasBegin<std::ranges::common_view<MutableView> const&>);
}
{
@@ -51,6 +65,13 @@ constexpr bool test() {
assert(begin == std::ranges::begin(view));
}
+ {
+ NonSimpleNonCommonView view{buf, buf + 8};
+ std::ranges::common_view<NonSimpleNonCommonView> common(view);
+ static_assert(!std::ranges::__simple_view<NonSimpleNonCommonView>);
+ static_assert(!std::is_same_v<decltype(common.begin()), decltype(std::as_const(common).begin())>);
+ }
+
return true;
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp
index 0565ed02f2716..8feb028e93893 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/end.pass.cpp
@@ -39,6 +39,13 @@ constexpr bool test() {
assert(base(end) == buf + 8);
}
+ {
+ NonSimpleNonCommonView view{buf, buf + 8};
+ std::ranges::common_view<NonSimpleNonCommonView> common(view);
+ static_assert(!std::ranges::__simple_view<NonSimpleNonCommonView>);
+ static_assert(!std::is_same_v<decltype(common.end()), decltype(std::as_const(common).end())>);
+ }
+
return true;
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h b/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
index 18354483fd329..dca4b7a33d348 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
@@ -90,4 +90,17 @@ struct NonCommonView : std::ranges::view_base {
static_assert( std::ranges::view<NonCommonView>);
static_assert(!std::ranges::common_range<NonCommonView>);
+
+template<bool Simple>
+struct NonCommonBaseView: std::ranges::view_base {
+ int* begin_;
+ int* end_;
+ constexpr explicit NonCommonBaseView(int* b, int* e) : begin_(b), end_(e) { }
+ constexpr auto begin() const { return static_cast<const int*>(begin_); }
+ constexpr auto end() const { return sentinel_wrapper<const int*>(end_); }
+ constexpr int *begin() requires (!Simple) { return begin_; }
+ constexpr auto end() requires (!Simple) { return sentinel_wrapper<int*>(end_); }
+};
+using NonSimpleNonCommonView = NonCommonBaseView<false>;
+
#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_COMMON_VIEW_TYPES_H
More information about the libcxx-commits
mailing list