[libcxx-commits] [libcxx] [libc++][mdspan][NFC] Simplify `std::extents` implementation (PR #196819)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun May 10 09:44:07 PDT 2026


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

None

>From a8065f0f666e007a358b1b9d0c66025a82729bb3 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Mon, 11 May 2026 00:41:54 +0800
Subject: [PATCH] [libc++][mdspan][NFC] Simplify std::extents implementation

---
 libcxx/include/__mdspan/extents.h | 61 +++++++++----------------------
 1 file changed, 18 insertions(+), 43 deletions(-)

diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h
index 379c762ace3ed..52c32f5052142 100644
--- a/libcxx/include/__mdspan/extents.h
+++ b/libcxx/include/__mdspan/extents.h
@@ -49,25 +49,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #if _LIBCPP_STD_VER >= 23
 
 namespace __mdspan_detail {
-
-// ------------------------------------------------------------------
-// ------------ __static_array --------------------------------------
-// ------------------------------------------------------------------
-// array like class which provides an array of static values with get
-template <class _Tp, _Tp... _Values>
-struct __static_array {
-  static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...};
-
-public:
-  _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); }
-  _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; }
-
-  template <size_t _Index>
-  _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() {
-    return __get(_Index);
-  }
-};
-
 // ------------------------------------------------------------------
 // ------------ __possibly_empty_array  -----------------------------
 // ------------------------------------------------------------------
@@ -120,35 +101,28 @@ struct __static_partial_sums {
 // array like class which has a mix of static and runtime values but
 // only stores the runtime values.
 // The type of the static and the runtime values can be different.
-// The position of a dynamic value is indicated through a tag value.
-template <class _TDynamic, class _TStatic, _TStatic _DynTag, _TStatic... _Values>
+// The position of a dynamic value is indicated by dynamic_extent.
+template <class _TDynamic, class _TStatic, _TStatic... _Values>
 struct __maybe_static_array {
-  static_assert(is_convertible<_TStatic, _TDynamic>::value,
+  static_assert(is_convertible_v<_TStatic, _TDynamic>,
                 "__maybe_static_array: _TStatic must be convertible to _TDynamic");
-  static_assert(is_convertible<_TDynamic, _TStatic>::value,
+  static_assert(is_convertible_v<_TDynamic, _TStatic>,
                 "__maybe_static_array: _TDynamic must be convertible to _TStatic");
 
 private:
   // Static values member
   static constexpr size_t __size_         = sizeof...(_Values);
-  static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0);
-  using _StaticValues _LIBCPP_NODEBUG     = __static_array<_TStatic, _Values...>;
+  static constexpr size_t __size_dynamic_ = ((_Values == dynamic_extent) + ... + 0);
   using _DynamicValues _LIBCPP_NODEBUG    = __possibly_empty_array<_TDynamic, __size_dynamic_>;
 
-  // Dynamic values member
+  static constexpr array<_TStatic, sizeof...(_Values)> __static_values_ = {_Values...};
   _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_;
 
   // static mapping of indices to the position in the dynamic values array
-  using _DynamicIdxMap _LIBCPP_NODEBUG = __static_partial_sums<static_cast<size_t>(_Values == _DynTag)...>;
-
-  template <size_t... _Indices>
-  _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept {
-    return _DynamicValues{((void)_Indices, 0)...};
-  }
+  using _DynamicIdxMap _LIBCPP_NODEBUG = __static_partial_sums<static_cast<size_t>(_Values == dynamic_extent)...>;
 
 public:
-  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept
-      : __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {}
+  _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept : __dyn_vals_{} {}
 
   // constructors from dynamic values only -- this covers the case for rank() == 0
   template <class... _DynVals>
@@ -172,8 +146,8 @@ struct __maybe_static_array {
     static_assert(sizeof...(_DynVals) == __size_, "Invalid number of values.");
     _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...};
     for (size_t __i = 0; __i < __size_; __i++) {
-      _TStatic __static_val = _StaticValues::__get(__i);
-      if (__static_val == _DynTag) {
+      _TStatic __static_val = __static_values_[__i];
+      if (__static_val == dynamic_extent) {
         __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i];
       } else
         // Not catching this could lead to out of bounds errors later
@@ -191,8 +165,8 @@ struct __maybe_static_array {
   _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) {
     static_assert(_Size == __size_ || __size_ == dynamic_extent);
     for (size_t __i = 0; __i < __size_; __i++) {
-      _TStatic __static_val = _StaticValues::__get(__i);
-      if (__static_val == _DynTag) {
+      _TStatic __static_val = __static_values_[__i];
+      if (__static_val == dynamic_extent) {
         __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]);
       } else
         // Not catching this could lead to out of bounds errors later
@@ -208,13 +182,15 @@ struct __maybe_static_array {
   // access functions
   _LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
-    return _StaticValues::__get(__i);
+    return __static_values_[__i];
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
-    _TStatic __static_val = _StaticValues::__get(__i);
-    return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val);
+    _TStatic __static_val = __static_values_[__i];
+    return __static_val == dynamic_extent
+             ? __dyn_vals_[_DynamicIdxMap::__get(__i)]
+             : static_cast<_TDynamic>(__static_val);
   }
   _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank");
@@ -296,8 +272,7 @@ class extents {
   static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0);
 
   // internal storage type using __maybe_static_array
-  using _Values _LIBCPP_NODEBUG =
-      __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>;
+  using _Values _LIBCPP_NODEBUG = __mdspan_detail::__maybe_static_array<_IndexType, size_t, _Extents...>;
   [[no_unique_address]] _Values __vals_;
 
 public:



More information about the libcxx-commits mailing list