[libcxx-commits] [libcxx] 86225b7 - [libc++][ranges] Fix missing `forward` in `views::enumerate` (#197635)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri May 15 02:19:50 PDT 2026


Author: Daniel Christian Mandolang
Date: 2026-05-15T12:19:45+03:00
New Revision: 86225b7efd86d7f8934654497cccc47b7a634115

URL: https://github.com/llvm/llvm-project/commit/86225b7efd86d7f8934654497cccc47b7a634115
DIFF: https://github.com/llvm/llvm-project/commit/86225b7efd86d7f8934654497cccc47b7a634115.diff

LOG: [libc++][ranges] Fix missing `forward` in `views::enumerate` (#197635)

This fixes #197404

---------

Co-authored-by: danielcm585 <danielchristianmandolang at gmail.com>

Added: 
    

Modified: 
    libcxx/include/__ranges/enumerate_view.h
    libcxx/test/std/ranges/range.adaptors/range.enumerate/adaptor.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__ranges/enumerate_view.h b/libcxx/include/__ranges/enumerate_view.h
index 3ba103b34b916..bb7696897af00 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;
 }
 


        


More information about the libcxx-commits mailing list