[libcxx-commits] [libcxx] [libc++][mdspan] Add missing `std::move` in `std::extents` (PR #196574)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri May 8 09:43:36 PDT 2026


https://github.com/eiytoq created https://github.com/llvm/llvm-project/pull/196574

Without this fix, libc++ rejects this example:

```cpp
#include <mdspan>

struct RValueInt {
  constexpr operator int() && noexcept { return 0; }
};

int main() {
  std::extents<int, std::dynamic_extent> e(RValueInt{});
}
```

>From 861fa2f3c2981885b386efebd2ec8699f52580c2 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sat, 9 May 2026 00:32:19 +0800
Subject: [PATCH] [libc++][mdspan] Add missing std::move in std::extents

---
 libcxx/include/__mdspan/extents.h                |  2 +-
 .../mdspan/extents/ctor_from_integral.pass.cpp   | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h
index 379c762ace3ed..087be833cb439 100644
--- a/libcxx/include/__mdspan/extents.h
+++ b/libcxx/include/__mdspan/extents.h
@@ -322,7 +322,7 @@ class extents {
              (is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&
              (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_))
   _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept
-      : __vals_(static_cast<index_type>(__dynvals)...) {
+      : __vals_(static_cast<index_type>(std::move(__dynvals))...) {
     // Not catching this could lead to out of bounds errors later
     // e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__dynvals...),
diff --git a/libcxx/test/std/containers/views/mdspan/extents/ctor_from_integral.pass.cpp b/libcxx/test/std/containers/views/mdspan/extents/ctor_from_integral.pass.cpp
index 24eb53b199338..ab8753faa7724 100644
--- a/libcxx/test/std/containers/views/mdspan/extents/ctor_from_integral.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/extents/ctor_from_integral.pass.cpp
@@ -38,6 +38,12 @@
 #include "CtorTestCombinations.h"
 #include "test_macros.h"
 
+struct RValueInt {
+  int val;
+  constexpr RValueInt(int v) : val(v) {}
+  constexpr operator int() && noexcept { return val; }
+};
+
 struct IntegralCtorTest {
   template <class E, class AllExtents, class Extents, size_t... Indices>
   static constexpr void test_construction(AllExtents all_ext, Extents ext, std::index_sequence<Indices...>) {
@@ -47,6 +53,12 @@ struct IntegralCtorTest {
   }
 };
 
+constexpr bool test_rvalue_conversion() {
+  std::dextents<int, 1> e(RValueInt{1});
+  assert(e.extent(0) == 1);
+  return true;
+}
+
 int main(int, char**) {
   test_index_type_combo<IntegralCtorTest>();
   static_assert(test_index_type_combo<IntegralCtorTest>());
@@ -65,5 +77,9 @@ int main(int, char**) {
   static_assert(std::is_convertible_v<IntType, int>, "Test helper IntType unexpectedly not convertible to int");
   static_assert(!std::is_constructible_v< std::extents<unsigned long, D>, IntType>,
                 "extents constructible from illegal arguments");
+
+  test_rvalue_conversion();
+  static_assert(test_rvalue_conversion());
+
   return 0;
 }



More information about the libcxx-commits mailing list