[libcxx-commits] [libcxx] [libc++][ranges] Fix missing `forward` in `views::enumerate` (PR #197635)
Daniel Christian Mandolang via libcxx-commits
libcxx-commits at lists.llvm.org
Thu May 14 21:23:15 PDT 2026
https://github.com/danielcm585 updated https://github.com/llvm/llvm-project/pull/197635
>From bb7fb16ff14fadd4f3668c3d432ebf0bbf58c1ed Mon Sep 17 00:00:00 2001
From: danielcm585 <danielchristianmandolang at gmail.com>
Date: Thu, 14 May 2026 16:26:24 +0800
Subject: [PATCH 1/2] [libc++][ranges] Fix missing forward
---
libcxx/include/__ranges/enumerate_view.h | 6 ++--
.../range.enumerate/adaptor.pass.cpp | 35 +++++++++++++++++++
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__ranges/enumerate_view.h b/libcxx/include/__ranges/enumerate_view.h
index 3ba103b34b916..d6412422f76b0 100644
--- a/libcxx/include/__ranges/enumerate_view.h
+++ b/libcxx/include/__ranges/enumerate_view.h
@@ -325,9 +325,9 @@ namespace __enumerate {
struct __fn : __range_adaptor_closure<__fn> {
template <class _Range>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
- operator()(_Range&& __range) noexcept(noexcept(/**/ enumerate_view<views::all_t<_Range>>(__range)))
- -> decltype(/*-------------------------------*/ enumerate_view<views::all_t<_Range>>(__range)) {
- return /*--------------------------------------*/ enumerate_view<views::all_t<_Range>>(__range);
+ operator()(_Range&& __range) noexcept(noexcept(/**/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))))
+ -> decltype(/*-------------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))) {
+ return /*--------------------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range));
}
};
diff --git a/libcxx/test/std/ranges/range.adaptors/range.enumerate/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.enumerate/adaptor.pass.cpp
index 7d87959b24a89..2452b75a45041 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.enumerate/adaptor.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.enumerate/adaptor.pass.cpp
@@ -90,6 +90,28 @@ static_assert(!std::is_invocable_v<decltype(std::views::enumerate), NotInvocable
static_assert(std::is_same_v<decltype(std::ranges::views::enumerate), decltype(std::views::enumerate)>);
+struct MoveOnlyView : std::ranges::view_base {
+ constexpr explicit MoveOnlyView(int* b, int* e) : begin_(b), end_(e) {}
+ MoveOnlyView(const MoveOnlyView&) = delete;
+ MoveOnlyView& operator=(const MoveOnlyView&) = delete;
+ constexpr MoveOnlyView(MoveOnlyView&& other) noexcept
+ : begin_(std::exchange(other.begin_, nullptr)), end_(std::exchange(other.end_, nullptr)) {}
+ MoveOnlyView& operator=(MoveOnlyView&&) = default;
+
+ constexpr int* begin() const { return begin_; }
+ constexpr int* end() const { return end_; }
+
+ int* begin_ = nullptr;
+ int* end_ = nullptr;
+};
+
+static_assert(std::ranges::view<MoveOnlyView>);
+static_assert(!std::copy_constructible<MoveOnlyView>);
+static_assert(!std::is_invocable_v<decltype(std::views::enumerate), MoveOnlyView&>);
+static_assert(!std::is_invocable_v<decltype(std::views::enumerate), const MoveOnlyView&>);
+static_assert(std::is_invocable_v<decltype(std::views::enumerate), MoveOnlyView>);
+static_assert(!std::is_invocable_v<decltype(std::views::enumerate), const MoveOnlyView>);
+
constexpr bool test() {
// Test `views::enumerate_view(v)`
{
@@ -127,6 +149,19 @@ constexpr bool test() {
compareViews(result, {{0, 'b'}, {1, 'a'}, {2, 'b'}, {3, 'a'}, {4, 'z'}, {5, 'm'}, {6, 't'}});
}
+ {
+ int buff[]{2, 3, 5, 7};
+ using Result = std::ranges::enumerate_view<MoveOnlyView>;
+ {
+ std::same_as<Result> decltype(auto) result = std::views::enumerate(MoveOnlyView(buff, buff + 4));
+ compareViews(std::move(result), {{0, 2}, {1, 3}, {2, 5}, {3, 7}});
+ }
+ {
+ std::same_as<Result> decltype(auto) result = MoveOnlyView(buff, buff + 4) | std::views::enumerate;
+ compareViews(std::move(result), {{0, 2}, {1, 3}, {2, 5}, {3, 7}});
+ }
+ }
+
return true;
}
>From 27e9b944d5079066ee74fe45288c66bf4ec535bb Mon Sep 17 00:00:00 2001
From: danielcm585 <danielchristianmandolang at gmail.com>
Date: Fri, 15 May 2026 12:22:57 +0800
Subject: [PATCH 2/2] fix formatting
---
libcxx/include/__ranges/enumerate_view.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__ranges/enumerate_view.h b/libcxx/include/__ranges/enumerate_view.h
index d6412422f76b0..c62fbcc923981 100644
--- a/libcxx/include/__ranges/enumerate_view.h
+++ b/libcxx/include/__ranges/enumerate_view.h
@@ -325,10 +325,9 @@ namespace __enumerate {
struct __fn : __range_adaptor_closure<__fn> {
template <class _Range>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
- operator()(_Range&& __range) noexcept(noexcept(/**/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))))
- -> decltype(/*-------------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))) {
- return /*--------------------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range));
- }
+ operator()(_Range&& __range) noexcept(noexcept(enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))))
+ -> decltype(/*--------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range))) {
+ return /*---------------------------------*/ enumerate_view<views::all_t<_Range>>(std::forward<_Range>(__range));
};
} // namespace __enumerate
More information about the libcxx-commits
mailing list