[libcxx-commits] [libcxx] [libc++] Partially implement P2642R6: Padded mdspan layouts (PR #187873)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Mar 23 21:07:40 PDT 2026


https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/187873

>From c9113a65e8c10305aff10019538d368811e41e4e Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Fri, 20 Mar 2026 20:57:03 +0800
Subject: [PATCH 1/6] impl

---
 libcxx/docs/Status/Cxx2cIssues.csv            |   2 +-
 libcxx/docs/Status/Cxx2cPapers.csv            |   2 +-
 libcxx/include/CMakeLists.txt                 |   4 +
 libcxx/include/__fwd/mdspan.h                 |  16 +
 libcxx/include/__mdspan/concepts.h            |  46 ++
 libcxx/include/__mdspan/layout_left_padded.h  | 415 +++++++++++++++++
 .../include/__mdspan/layout_padded_common.h   |  98 ++++
 libcxx/include/__mdspan/layout_right_padded.h | 428 ++++++++++++++++++
 libcxx/include/__mdspan/layout_stride.h       |  19 +-
 libcxx/include/mdspan                         | 171 +++++++
 libcxx/modules/std/mdspan.inc                 |   5 +
 .../layout_left_padded/comparison.pass.cpp    |  91 ++++
 .../layout_left_padded/ctor.copy.pass.cpp     |  55 +++
 .../layout_left_padded/ctor.default.pass.cpp  |  53 +++
 .../layout_left_padded/ctor.extents.pass.cpp  |  59 +++
 .../ctor.layout_left.pass.cpp                 |  79 ++++
 .../ctor.layout_right.pass.cpp                |  74 +++
 .../ctor.layout_right_padded.pass.cpp         |  74 +++
 .../ctor.layout_stride.pass.cpp               |  78 ++++
 .../ctor.mapping.assert.pass.cpp              |  53 +++
 .../layout_left_padded/ctor.mapping.pass.cpp  |  86 ++++
 .../layout_left_padded/ctor.padding.pass.cpp  |  52 +++
 .../layout_left_padded/extents.verify.cpp     |  36 ++
 .../index_operator.pass.cpp                   | 105 +++++
 .../layout_left_padded/properties.pass.cpp    |  88 ++++
 .../required_span_size.pass.cpp               |  53 +++
 .../static_requirements.pass.cpp              |  68 +++
 .../mdspan/layout_left_padded/stride.pass.cpp |  61 +++
 .../layout_right_padded/comparison.pass.cpp   |  91 ++++
 .../layout_right_padded/ctor.copy.pass.cpp    |  59 +++
 .../layout_right_padded/ctor.default.pass.cpp |  53 +++
 .../layout_right_padded/ctor.extents.pass.cpp |  59 +++
 .../ctor.layout_left.pass.cpp                 |  74 +++
 .../ctor.layout_left_padded.pass.cpp          |  74 +++
 .../ctor.layout_right.pass.cpp                |  79 ++++
 .../ctor.layout_stride.pass.cpp               |  78 ++++
 .../ctor.mapping.assert.pass.cpp              |  52 +++
 .../layout_right_padded/ctor.mapping.pass.cpp |  86 ++++
 .../layout_right_padded/ctor.padding.pass.cpp |  52 +++
 .../layout_right_padded/extents.verify.cpp    |  36 ++
 .../index_operator.pass.cpp                   | 105 +++++
 .../layout_right_padded/properties.pass.cpp   |  87 ++++
 .../required_span_size.pass.cpp               |  53 +++
 .../static_requirements.pass.cpp              |  68 +++
 .../layout_right_padded/stride.pass.cpp       |  61 +++
 45 files changed, 3518 insertions(+), 20 deletions(-)
 create mode 100644 libcxx/include/__mdspan/concepts.h
 create mode 100644 libcxx/include/__mdspan/layout_left_padded.h
 create mode 100644 libcxx/include/__mdspan/layout_padded_common.h
 create mode 100644 libcxx/include/__mdspan/layout_right_padded.h
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/comparison.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_left.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right_padded.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_stride.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.assert.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.padding.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/index_operator.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left_padded/stride.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/comparison.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left_padded.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_right.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_stride.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.assert.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.padding.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/index_operator.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right_padded/stride.pass.cpp

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 60b1bd6ff70da..5036ebfb1691a 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -204,7 +204,7 @@
 "`LWG4366 <https://wg21.link/LWG4366>`__","Heterogeneous comparison of ``expected`` may be ill-formed","2025-11 (Kona)","","","`#171362 <https://github.com/llvm/llvm-project/issues/171362>`__",""
 "`LWG4369 <https://wg21.link/LWG4369>`__","``check-types`` function for ``upon_error`` and ``upon_stopped`` is wrong","2025-11 (Kona)","","","`#171363 <https://github.com/llvm/llvm-project/issues/171363>`__",""
 "`LWG4370 <https://wg21.link/LWG4370>`__","Comparison of ``optional<T>`` to ``T`` may be ill-formed","2025-11 (Kona)","|Complete|","22","`#171364 <https://github.com/llvm/llvm-project/issues/171364>`__",""
-"`LWG4372 <https://wg21.link/LWG4372>`__","Weaken *Mandates:* for dynamic padding values in padded layouts","2025-11 (Kona)","","","`#171365 <https://github.com/llvm/llvm-project/issues/171365>`__",""
+"`LWG4372 <https://wg21.link/LWG4372>`__","Weaken *Mandates:* for dynamic padding values in padded layouts","2025-11 (Kona)","|Complete|","23","`#171365 <https://github.com/llvm/llvm-project/issues/171365>`__",""
 "`LWG4375 <https://wg21.link/LWG4375>`__","``std::simd::bit_ceil`` should not be ``noexcept``","2025-11 (Kona)","","","`#171366 <https://github.com/llvm/llvm-project/issues/171366>`__",""
 "`LWG4376 <https://wg21.link/LWG4376>`__","ABI tag in return type of [simd.mask.unary] is overconstrained","2025-11 (Kona)","","","`#171367 <https://github.com/llvm/llvm-project/issues/171367>`__",""
 "`LWG4377 <https://wg21.link/LWG4377>`__","Misleading note about lock-free property of ``std::atomic_ref``","2025-11 (Kona)","","","`#171368 <https://github.com/llvm/llvm-project/issues/171368>`__",""
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 29642fc53cac6..3d84652940a3d 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -60,7 +60,7 @@
 "`P2810R4 <https://wg21.link/P2810R4>`__","``is_debugger_present`` ``is_replaceable``","2024-03 (Tokyo)","","","`#105422 <https://github.com/llvm/llvm-project/issues/105422>`__",""
 "`P1068R11 <https://wg21.link/P1068R11>`__","Vector API for random number generation","2024-03 (Tokyo)","","","`#105423 <https://github.com/llvm/llvm-project/issues/105423>`__",""
 "`P2944R3 <https://wg21.link/P2944R3>`__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Complete|","22","`#105424 <https://github.com/llvm/llvm-project/issues/105424>`__","The changes to ``tuple``'s equality overload from P2165R4 are not yet implemented."
-"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","","`#105425 <https://github.com/llvm/llvm-project/issues/105425>`__",""
+"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","|Partial|","23","`#105425 <https://github.com/llvm/llvm-project/issues/105425>`__",""
 "`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19","`#105426 <https://github.com/llvm/llvm-project/issues/105426>`__",""
 "","","","","","",""
 "`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20","`#105427 <https://github.com/llvm/llvm-project/issues/105427>`__",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 53165f0336b2d..474f21bc4959d 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -572,9 +572,13 @@ set(files
   __math/trigonometric_functions.h
   __mbstate_t.h
   __mdspan/aligned_accessor.h
+  __mdspan/concepts.h
   __mdspan/default_accessor.h
   __mdspan/extents.h
   __mdspan/layout_left.h
+  __mdspan/layout_left_padded.h
+  __mdspan/layout_padded_common.h
+  __mdspan/layout_right_padded.h
   __mdspan/layout_right.h
   __mdspan/layout_stride.h
   __mdspan/mdspan.h
diff --git a/libcxx/include/__fwd/mdspan.h b/libcxx/include/__fwd/mdspan.h
index 8889567a047f6..8c069577ab2a9 100644
--- a/libcxx/include/__fwd/mdspan.h
+++ b/libcxx/include/__fwd/mdspan.h
@@ -18,6 +18,8 @@
 #define _LIBCPP___MDSPAN_LAYOUTS_H
 
 #include <__config>
+#include <cstddef>
+#include <span>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -48,6 +50,20 @@ struct layout_stride {
   class mapping;
 };
 
+#  if _LIBCPP_STD_VER >= 26
+template <size_t _PaddingValue = dynamic_extent>
+struct layout_left_padded {
+  template <class _Extents>
+  class mapping;
+};
+
+template <size_t _PaddingValue = dynamic_extent>
+struct layout_right_padded {
+  template <class _Extents>
+  class mapping;
+};
+#  endif
+
 #endif // _LIBCPP_STD_VER >= 23
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__mdspan/concepts.h b/libcxx/include/__mdspan/concepts.h
new file mode 100644
index 0000000000000..9b5d321c79cdb
--- /dev/null
+++ b/libcxx/include/__mdspan/concepts.h
@@ -0,0 +1,46 @@
+#ifndef _LIBCPP___MDSPAN_CONCEPT_H
+#define _LIBCPP___MDSPAN_CONCEPT_H
+
+#include <__assert>
+#include <__concepts/same_as.h>
+#include <__config>
+#include <__mdspan/extents.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace __mdspan_detail {
+  
+template <class _Layout, class _Mapping>
+constexpr bool __is_mapping_of =
+    is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>;
+
+template <class _Mapping>
+concept __layout_mapping_alike = requires {
+  requires __is_mapping_of<typename _Mapping::layout_type, _Mapping>;
+  requires __is_extents_v<typename _Mapping::extents_type>;
+  { _Mapping::is_always_strided() } -> same_as<bool>;
+  { _Mapping::is_always_exhaustive() } -> same_as<bool>;
+  { _Mapping::is_always_unique() } -> same_as<bool>;
+  bool_constant<_Mapping::is_always_strided()>::value;
+  bool_constant<_Mapping::is_always_exhaustive()>::value;
+  bool_constant<_Mapping::is_always_unique()>::value;
+};
+
+} // namespace __mdspan_detail
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___MDSPAN_CONCEPT_H
diff --git a/libcxx/include/__mdspan/layout_left_padded.h b/libcxx/include/__mdspan/layout_left_padded.h
new file mode 100644
index 0000000000000..f2709975c49bf
--- /dev/null
+++ b/libcxx/include/__mdspan/layout_left_padded.h
@@ -0,0 +1,415 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//                        Kokkos v. 4.0
+//       Copyright (2022) National Technology & Engineering
+//               Solutions of Sandia, LLC (NTESS).
+//
+// Under the terms of Contract DE-NA0003525 with NTESS,
+// the U.S. Government retains certain rights in this software.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MDSPAN_LAYOUT_LEFT_PADDED_H
+#define _LIBCPP___MDSPAN_LAYOUT_LEFT_PADDED_H
+
+#include <__assert>
+#include <__config>
+#include <__fwd/mdspan.h>
+#include <__mdspan/concepts.h>
+#include <__mdspan/extents.h>
+#include <__mdspan/layout_left.h>
+#include <__mdspan/layout_padded_common.h>
+#include <__mdspan/layout_right.h>
+#include <__mdspan/layout_stride.h>
+#include <__memory/addressof.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_convertible.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__utility/integer_sequence.h>
+#include <array>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <size_t _PaddingValue>
+template <class _Extents>
+class layout_left_padded<_PaddingValue>::mapping {
+public:
+  static_assert(__mdspan_detail::__is_extents<_Extents>::value,
+                "layout_left_padded::mapping template argument must be a specialization of extents.");
+
+  static constexpr size_t padding_value = _PaddingValue;
+
+  using extents_type = _Extents;
+  using index_type   = extents_type::index_type;
+  using size_type    = extents_type::size_type;
+  using rank_type    = extents_type::rank_type;
+  using layout_type  = layout_left_padded;
+
+private:
+  static constexpr rank_type __rank_            = extents_type::rank();
+  static constexpr size_t __first_static_extent = __rank_ == 0 ? 0uz : extents_type::static_extent(0);
+
+  static constexpr size_t __static_padding_stride = [] {
+    if constexpr (__rank_ <= 1)
+      return 0uz;
+    if constexpr (padding_value == dynamic_extent || __first_static_extent == dynamic_extent)
+      return dynamic_extent;
+    return __mdspan_detail::__least_multiple_at_least(padding_value, __first_static_extent);
+  }();
+
+  // Do not store value if __static_padding_stride is not dynamic_extent.
+  using __stride_1_type = std::extents<index_type, __static_padding_stride>;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type __stride_1() const noexcept {
+    if constexpr (__rank_ <= 1)
+      return static_cast<index_type>(0);
+    if constexpr (__static_padding_stride != dynamic_extent)
+      return static_cast<index_type>(__static_padding_stride);
+    return __stride_1_.extent(0);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool __index_space_size_is_representable(const extents_type& __ext) {
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      if (__ext.extent(__r) == static_cast<index_type>(0))
+        return true;
+    }
+
+    index_type __prod = static_cast<index_type>(1);
+
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+
+    return true;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool
+  __padded_product_is_representable(const extents_type& __ext, index_type __stride_1) {
+    if (__stride_1 == static_cast<index_type>(0))
+      return true;
+    for (rank_type __r = 1; __r < __rank_; ++__r) {
+      if (__ext.extent(__r) == static_cast<index_type>(0))
+        return true;
+    }
+
+    index_type __prod = __stride_1;
+    for (rank_type __r = 1; __r < __rank_; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+    return true;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static consteval bool __static_padded_product_is_representable() {
+    if constexpr (__rank_ <= 1 || padding_value == dynamic_extent || extents_type::rank_dynamic() > 0)
+      return true;
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      if (extents_type::static_extent(__r) == 0)
+        return true;
+    }
+    if constexpr (__static_padding_stride == dynamic_extent ||
+                  !__mdspan_detail::__is_representable_as<index_type>(__static_padding_stride))
+      return false;
+    size_t __prod = __static_padding_stride;
+    for (rank_type __r = 1; __r < __rank_; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, extents_type::static_extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+    return __mdspan_detail::__is_representable_as<index_type>(__prod);
+  }
+
+  static_assert(extents_type::rank_dynamic() != 0 || __index_space_size_is_representable(extents_type{}),
+                "layout_left_padded::mapping index space for static extents must be representable as index_type.");
+
+  static_assert(padding_value == dynamic_extent || __mdspan_detail::__is_representable_as<index_type>(padding_value),
+                "layout_left_padded::mapping padding_value must be representable as index_type.");
+
+  static_assert(__rank_ <= 1 || padding_value == dynamic_extent || __first_static_extent == dynamic_extent ||
+                    (__mdspan_detail::__least_multiple_at_least_is_representable_as<size_t>(
+                         padding_value, __first_static_extent) &&
+                     __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+                         padding_value, __first_static_extent)),
+                "layout_left_padded::mapping padded stride for the first static extent must be representable as "
+                "size_t and index_type.");
+
+  static_assert(__static_padded_product_is_representable(),
+                "layout_left_padded::mapping required span size for static extents must be representable as size_t "
+                "and index_type.");
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept : mapping(extents_type{}) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) : __extents_(__ext) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __index_space_size_is_representable(__ext),
+        "layout_left_padded::mapping(extents): index space size must be representable as index_type.");
+
+    if constexpr (__rank_ > 1) {
+      index_type __stride_1 = 0;
+      if constexpr (padding_value == dynamic_extent) {
+        __stride_1 = __ext.extent(0);
+      } else {
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+                static_cast<index_type>(padding_value), __ext.extent(0)),
+            "layout_left_padded::mapping(extents): padded stride must be representable as index_type.");
+        __stride_1 =
+            __mdspan_detail::__least_multiple_at_least(static_cast<index_type>(padding_value), __ext.extent(0));
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            __padded_product_is_representable(__ext, __stride_1),
+            "layout_left_padded::mapping(extents): required span size must be representable as index_type.");
+      }
+      if constexpr (__static_padding_stride == dynamic_extent)
+        __stride_1_ = __stride_1_type(__stride_1);
+    }
+  }
+
+  template <class _OtherIndexType>
+    requires is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType>
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext, _OtherIndexType __pad) : __extents_(__ext) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__pad),
+        "layout_left_padded::mapping(extents, pad): pad must be representable as index_type.");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        static_cast<index_type>(__pad) > 0, "layout_left_padded::mapping(extents, pad): pad must be greater than 0.");
+
+    if constexpr (padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(padding_value == static_cast<index_type>(__pad),
+                                          "layout_left_padded::mapping(extents, pad): pad must equal padding_value.");
+
+    if constexpr (__rank_ > 1) {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+              static_cast<index_type>(__pad), __ext.extent(0)),
+          "layout_left_padded::mapping(extents, pad): padded stride must be representable as index_type.");
+
+      const index_type __stride_1 =
+          __mdspan_detail::__least_multiple_at_least(static_cast<index_type>(__pad), __ext.extent(0));
+
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __padded_product_is_representable(__ext, __stride_1),
+          "layout_left_padded::mapping(extents, pad): required span size must be representable as index_type.");
+
+      if constexpr (__static_padding_stride == dynamic_extent)
+        __stride_1_ = __stride_1_type(__stride_1);
+    }
+  }
+
+  template <class _OtherExtents>
+    requires is_constructible_v<extents_type, _OtherExtents>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
+      mapping(const layout_left::mapping<_OtherExtents>& __other)
+      : mapping(extents_type(__other.extents())) {
+    static_assert(_OtherExtents::rank() <= 1 || __static_padding_stride == dynamic_extent ||
+                  _OtherExtents::static_extent(0) == dynamic_extent ||
+                  __static_padding_stride == _OtherExtents::static_extent(0));
+
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent) {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(1) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value), static_cast<index_type>(__other.extents().extent(0))),
+          "layout_left_padded::mapping from layout_left ctor: source stride must match the padded stride implied by "
+          "padding_value.");
+    }
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_left_padded::mapping from layout_left ctor: other.required_span_size() must be representable as "
+        "index_type.");
+  }
+
+  template <class _OtherExtents>
+    requires is_constructible_v<extents_type, _OtherExtents>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!(__rank_ == 0 && is_convertible_v<_OtherExtents, extents_type>))
+      mapping(const layout_stride::mapping<_OtherExtents>& __other)
+      : __extents_(extents_type(__other.extents())) {
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(1) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value), static_cast<index_type>(__other.extents().extent(0))),
+          "layout_left_padded::mapping from layout_stride ctor: source stride must match the padded stride implied by "
+          "padding_value.");
+
+    if constexpr (__rank_ > 0)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(0) == 1, "layout_left_padded::mapping from layout_stride ctor: stride(0) must equal 1.");
+
+    if constexpr (__rank_ > 2) {
+      using _Common      = common_type_t<index_type, typename layout_stride::mapping<_OtherExtents>::index_type>;
+      _Common __expected = static_cast<_Common>(__other.stride(1));
+      for (rank_type __r = 2; __r < __rank_; ++__r) {
+        __expected *= static_cast<_Common>(__other.extents().extent(__r - 1));
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            static_cast<_Common>(__other.stride(__r)) == __expected,
+            "layout_left_padded::mapping from layout_stride ctor: strides are not compatible with layout_left_padded.");
+      }
+    }
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_left_padded::mapping from layout_stride ctor: other.required_span_size() must be representable as "
+        "index_type.");
+
+    if constexpr (__rank_ > 1 && __static_padding_stride == dynamic_extent) {
+#  if 0 // TODO
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__is_representable_as<index_type>(__other.stride(1)),
+          "layout_left_padded::mapping from layout_stride ctor: source padded stride must be representable as "
+          "index_type.");
+#  endif
+      __stride_1_ = __stride_1_type(static_cast<index_type>(__other.stride(1)));
+    }
+  }
+
+  template <class _LayoutLeftPaddedMapping>
+    requires __mdspan_detail::__layout_left_padded_mapping_of<_LayoutLeftPaddedMapping> &&
+             is_constructible_v<extents_type, typename _LayoutLeftPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutLeftPaddedMapping::extents_type, extents_type> ||
+      (__rank_ > 1 && (padding_value != dynamic_extent || _LayoutLeftPaddedMapping::padding_value == dynamic_extent)))
+      mapping(const _LayoutLeftPaddedMapping& __other)
+      : __extents_(extents_type(__other.extents())) {
+    static_assert(
+        __rank_ <= 1 || padding_value == dynamic_extent || _LayoutLeftPaddedMapping::padding_value == dynamic_extent ||
+            padding_value == _LayoutLeftPaddedMapping::padding_value,
+        "layout_left_padded::mapping converting ctor: incompatible static padding values.");
+
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(1) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value), static_cast<index_type>(__other.extents().extent(0))),
+          "layout_left_padded::mapping from layout_left_padded ctor: source stride must match the padded stride "
+          "implied by padding_value.");
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_left_padded::mapping from layout_left_padded ctor: other.required_span_size() must be representable as "
+        "index_type.");
+
+    if constexpr (__rank_ > 1 && __static_padding_stride == dynamic_extent) {
+#  if 0 // TODO
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__is_representable_as<index_type>(__other.stride(1)),
+          "layout_left_padded::mapping from layout_left_padded ctor: source padded stride must be representable as "
+          "index_type.");
+#  endif
+      __stride_1_ = __stride_1_type(static_cast<index_type>(__other.stride(1)));
+    }
+  }
+
+  template <class _LayoutRightPaddedMapping>
+    requires(__mdspan_detail::__layout_right_padded_mapping_of<_LayoutRightPaddedMapping> ||
+             __mdspan_detail::__layout_right_mapping_of<_LayoutRightPaddedMapping>) &&
+            (__rank_ <= 1) && is_constructible_v<extents_type, typename _LayoutRightPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutRightPaddedMapping::extents_type, extents_type>)
+      mapping(const _LayoutRightPaddedMapping& __other) noexcept
+      : __extents_(extents_type(__other.extents())) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_left_padded::mapping converting ctor: other.required_span_size() must be representable as index_type.");
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr array<index_type, __rank_> strides() const noexcept {
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      return array<index_type, __rank_>{stride(_Pos)...};
+    }(make_index_sequence<__rank_>());
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept {
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      if (((__extents_.extent(_Pos) == static_cast<index_type>(0)) || ...))
+        return static_cast<index_type>(0);
+
+      return static_cast<index_type>(
+          (*this)(static_cast<index_type>(__extents_.extent(_Pos) - static_cast<index_type>(1))...) +
+          static_cast<index_type>(1));
+    }(make_index_sequence<__rank_>());
+  }
+
+  template <class... _Indices>
+    requires(sizeof...(_Indices) == __rank_) && (is_convertible_v<_Indices, index_type> && ...) &&
+            (is_nothrow_constructible_v<index_type, _Indices> && ...)
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
+                                 "layout_left_padded::mapping: out of bounds indexing.");
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      return ((static_cast<index_type>(__idx) * stride(_Pos)) + ... + static_cast<index_type>(0));
+    }(make_index_sequence<sizeof...(_Indices)>());
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
+    if constexpr (__rank_ <= 1)
+      return true;
+    if constexpr (__first_static_extent == dynamic_extent || __static_padding_stride == dynamic_extent)
+      return false;
+    return __first_static_extent == __static_padding_stride;
+  }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const noexcept {
+    if constexpr (__rank_ <= 1)
+      return true;
+    return extents().extent(0) == stride(1);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__r < __rank_, "layout_left_padded::mapping::stride(): invalid rank index.");
+
+    if (__r == 0)
+      return static_cast<index_type>(1);
+
+    index_type __stride = __stride_1();
+    for (rank_type __i = 1; __i < __r; ++__i)
+      __stride *= __extents_.extent(__i);
+    return __stride;
+  }
+
+  template <class _LayoutLeftPaddedMapping>
+    requires __mdspan_detail::__layout_left_padded_mapping_of<_LayoutLeftPaddedMapping> &&
+             (_LayoutLeftPaddedMapping::extents_type::rank() == __rank_)
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+  operator==(const mapping& __x, const _LayoutLeftPaddedMapping& __y) noexcept {
+    return __x.extents() == __y.extents() && (__rank_ < 2 || __x.stride(1) == __y.stride(1));
+  }
+
+private:
+  _LIBCPP_NO_UNIQUE_ADDRESS __stride_1_type __stride_1_{};
+  _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
+};
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___MDSPAN_LAYOUT_LEFT_PADDED_H
diff --git a/libcxx/include/__mdspan/layout_padded_common.h b/libcxx/include/__mdspan/layout_padded_common.h
new file mode 100644
index 0000000000000..aae860f6f8d87
--- /dev/null
+++ b/libcxx/include/__mdspan/layout_padded_common.h
@@ -0,0 +1,98 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//                        Kokkos v. 4.0
+//       Copyright (2022) National Technology & Engineering
+//               Solutions of Sandia, LLC (NTESS).
+//
+// Under the terms of Contract DE-NA0003525 with NTESS,
+// the U.S. Government retains certain rights in this software.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MDSPAN_LAYOUT_PADDED_COMMON_H
+#define _LIBCPP___MDSPAN_LAYOUT_PADDED_COMMON_H
+
+#include <__config>
+#include <__fwd/mdspan.h>
+#include <__mdspan/concepts.h>
+#include <__memory/addressof.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+namespace __mdspan_detail {
+
+template <class _Integral>
+_LIBCPP_HIDE_FROM_ABI constexpr _Integral __least_multiple_at_least(_Integral __multiplier, _Integral __minimum) {
+  if (__multiplier == static_cast<_Integral>(0))
+    return __minimum;
+
+  _Integral __factor = __minimum / __multiplier;
+  if (__minimum % __multiplier != static_cast<_Integral>(0))
+    ++__factor;
+
+  return __factor * __multiplier;
+}
+
+template <class _To, class _Integral>
+_LIBCPP_HIDE_FROM_ABI constexpr bool
+__least_multiple_at_least_is_representable_as(_Integral __multiplier, _Integral __minimum) {
+  if (__multiplier == static_cast<_Integral>(0))
+    return __mdspan_detail::__is_representable_as<_To>(__minimum);
+
+  _Integral __factor = __minimum / __multiplier;
+  if (__minimum % __multiplier != static_cast<_Integral>(0)) {
+    bool __overflowed_add = __builtin_add_overflow(__factor, static_cast<_Integral>(1), std::addressof(__factor));
+    if (__overflowed_add)
+      return false;
+  }
+
+  _Integral __result    = 0;
+  bool __overflowed_mul = __builtin_mul_overflow(__factor, __multiplier, std::addressof(__result));
+  return !__overflowed_mul && __mdspan_detail::__is_representable_as<_To>(__result);
+}
+
+template <template <size_t> class _LayoutTemplate, class _Layout>
+struct __is_layout_specialization_of : false_type {};
+
+template <template <size_t> class _LayoutTemplate, size_t _PaddingValue>
+struct __is_layout_specialization_of<_LayoutTemplate, _LayoutTemplate<_PaddingValue>> : true_type {};
+
+template <class _Mapping>
+concept __layout_left_padded_mapping_of =
+    __layout_mapping_alike<_Mapping> &&
+    __is_layout_specialization_of<layout_left_padded, typename _Mapping::layout_type>::value;
+
+template <class _Mapping>
+concept __layout_right_padded_mapping_of =
+    __layout_mapping_alike<_Mapping> &&
+    __is_layout_specialization_of<layout_right_padded, typename _Mapping::layout_type>::value;
+
+template <class _Mapping>
+concept __layout_right_mapping_of = __layout_mapping_alike<_Mapping> && __is_mapping_of<layout_right, _Mapping>;
+
+template <class _Mapping>
+concept __layout_left_mapping_of = __layout_mapping_alike<_Mapping> && __is_mapping_of<layout_left, _Mapping>;
+
+} // namespace __mdspan_detail
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___MDSPAN_LAYOUT_PADDED_COMMON_H
diff --git a/libcxx/include/__mdspan/layout_right_padded.h b/libcxx/include/__mdspan/layout_right_padded.h
new file mode 100644
index 0000000000000..2d89722536ba2
--- /dev/null
+++ b/libcxx/include/__mdspan/layout_right_padded.h
@@ -0,0 +1,428 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//                        Kokkos v. 4.0
+//       Copyright (2022) National Technology & Engineering
+//               Solutions of Sandia, LLC (NTESS).
+//
+// Under the terms of Contract DE-NA0003525 with NTESS,
+// the U.S. Government retains certain rights in this software.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MDSPAN_LAYOUT_RIGHT_PADDED_H
+#define _LIBCPP___MDSPAN_LAYOUT_RIGHT_PADDED_H
+
+#include <__assert>
+#include <__config>
+#include <__fwd/mdspan.h>
+#include <__mdspan/concepts.h>
+#include <__mdspan/extents.h>
+#include <__mdspan/layout_left.h>
+#include <__mdspan/layout_padded_common.h>
+#include <__mdspan/layout_right.h>
+#include <__mdspan/layout_stride.h>
+#include <__memory/addressof.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_convertible.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__utility/integer_sequence.h>
+#include <array>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <size_t _PaddingValue>
+template <class _Extents>
+class layout_right_padded<_PaddingValue>::mapping {
+public:
+  static_assert(__mdspan_detail::__is_extents<_Extents>::value,
+                "layout_right_padded::mapping template argument must be a specialization of extents.");
+
+  static constexpr size_t padding_value = _PaddingValue;
+
+  using extents_type = _Extents;
+  using index_type   = extents_type::index_type;
+  using size_type    = extents_type::size_type;
+  using rank_type    = extents_type::rank_type;
+  using layout_type  = layout_right_padded;
+
+private:
+  static constexpr rank_type __rank_           = extents_type::rank();
+  static constexpr size_t __last_static_extent = __rank_ == 0 ? 0uz : extents_type::static_extent(__rank_ - 1);
+
+  static constexpr size_t __static_padding_stride = [] {
+    if constexpr (__rank_ <= 1)
+      return 0uz;
+    if constexpr (padding_value == dynamic_extent || __last_static_extent == dynamic_extent)
+      return dynamic_extent;
+    return __mdspan_detail::__least_multiple_at_least(padding_value, __last_static_extent);
+  }();
+
+  using __stride_rm2_type = std::extents<index_type, __static_padding_stride>;
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool __index_space_size_is_representable(const extents_type& __ext) {
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      if (__ext.extent(__r) == static_cast<index_type>(0))
+        return true;
+    }
+
+    index_type __prod = static_cast<index_type>(1);
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+
+    return true;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool
+  __padded_product_is_representable(const extents_type& __ext, index_type __stride_rm2) {
+    if (__stride_rm2 == static_cast<index_type>(0))
+      return true;
+    for (rank_type __r = 0; __r < __rank_ - 1; ++__r) {
+      if (__ext.extent(__r) == static_cast<index_type>(0))
+        return true;
+    }
+
+    index_type __prod = __stride_rm2;
+    for (rank_type __r = 0; __r < __rank_ - 1; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+    return true;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type __stride_rm2() const noexcept {
+    if constexpr (__rank_ <= 1)
+      return static_cast<index_type>(0);
+    if constexpr (__static_padding_stride != dynamic_extent)
+      return static_cast<index_type>(__static_padding_stride);
+    return __stride_rm2_.extent(0);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static consteval bool __static_padded_product_is_representable() {
+    if constexpr (__rank_ <= 1 || padding_value == dynamic_extent || extents_type::rank_dynamic() > 0)
+      return true;
+    for (rank_type __r = 0; __r < __rank_; ++__r) {
+      if (extents_type::static_extent(__r) == 0)
+        return true;
+    }
+    if constexpr (__static_padding_stride == dynamic_extent ||
+                  !__mdspan_detail::__is_representable_as<index_type>(__static_padding_stride))
+      return false;
+    size_t __prod = __static_padding_stride;
+    for (rank_type __r = 0; __r < __rank_ - 1; ++__r) {
+      bool __overflowed = __builtin_mul_overflow(__prod, extents_type::static_extent(__r), std::addressof(__prod));
+      if (__overflowed)
+        return false;
+    }
+    return __mdspan_detail::__is_representable_as<index_type>(__prod);
+  }
+
+  static_assert(extents_type::rank_dynamic() != 0 || __index_space_size_is_representable(extents_type{}),
+                "layout_right_padded::mapping index space for static extents must be representable as index_type.");
+
+  static_assert(padding_value == dynamic_extent || __mdspan_detail::__is_representable_as<index_type>(padding_value),
+                "layout_right_padded::mapping padding_value must be representable as index_type.");
+
+  static_assert(__rank_ <= 1 || padding_value == dynamic_extent || __last_static_extent == dynamic_extent ||
+                    (__mdspan_detail::__least_multiple_at_least_is_representable_as<size_t>(
+                         padding_value, __last_static_extent) &&
+                     __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+                         padding_value, __last_static_extent)),
+                "layout_right_padded::mapping padded stride for the last static extent must be representable as "
+                "size_t and index_type.");
+
+  static_assert(__static_padded_product_is_representable(),
+                "layout_right_padded::mapping required span size for static extents must be representable as size_t "
+                "and index_type.");
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept : mapping(extents_type{}) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) : __extents_(__ext) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __index_space_size_is_representable(__ext),
+        "layout_right_padded::mapping(extents): index space size must be representable as index_type.");
+
+    if constexpr (__rank_ > 1) {
+      index_type __stride_rm2 = 0;
+      if constexpr (padding_value == dynamic_extent) {
+        __stride_rm2 = __ext.extent(__rank_ - 1);
+      } else {
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+                static_cast<index_type>(padding_value), __ext.extent(__rank_ - 1)),
+            "layout_right_padded::mapping(extents): padded stride must be representable as index_type.");
+        __stride_rm2 = __mdspan_detail::__least_multiple_at_least(
+            static_cast<index_type>(padding_value), __ext.extent(__rank_ - 1));
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            __padded_product_is_representable(__ext, __stride_rm2),
+            "layout_right_padded::mapping(extents): required span size must be representable as index_type.");
+      }
+      if constexpr (__static_padding_stride == dynamic_extent)
+        __stride_rm2_ = __stride_rm2_type(__stride_rm2);
+    }
+  }
+
+  template <class _OtherIndexType>
+    requires is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType>
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext, _OtherIndexType __pad) : __extents_(__ext) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__pad),
+        "layout_right_padded::mapping(extents, pad): pad must be representable as index_type.");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        static_cast<index_type>(__pad) > 0, "layout_right_padded::mapping(extents, pad): pad must be greater than 0.");
+
+    if constexpr (padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(padding_value == static_cast<index_type>(__pad),
+                                          "layout_right_padded::mapping(extents, pad): pad must equal padding_value.");
+
+    if constexpr (__rank_ > 1) {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__least_multiple_at_least_is_representable_as<index_type>(
+              static_cast<index_type>(__pad), __ext.extent(__rank_ - 1)),
+          "layout_right_padded::mapping(extents, pad): padded stride must be representable as index_type.");
+
+      const index_type __stride_rm2 =
+          __mdspan_detail::__least_multiple_at_least(static_cast<index_type>(__pad), __ext.extent(__rank_ - 1));
+
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __padded_product_is_representable(__ext, __stride_rm2),
+          "layout_right_padded::mapping(extents, pad): required span size must be representable as index_type.");
+
+      if constexpr (__static_padding_stride == dynamic_extent)
+        __stride_rm2_ = __stride_rm2_type(__stride_rm2);
+    }
+  }
+
+  template <class _OtherExtents>
+    requires is_constructible_v<extents_type, _OtherExtents>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
+      mapping(const layout_right::mapping<_OtherExtents>& __other)
+      : mapping(extents_type(__other.extents())) {
+    static_assert(_OtherExtents::rank() <= 1 || __static_padding_stride == dynamic_extent ||
+                  _OtherExtents::static_extent(_OtherExtents::rank() - 1) == dynamic_extent ||
+                  __static_padding_stride == _OtherExtents::static_extent(_OtherExtents::rank() - 1));
+
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent) {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(__rank_ - 2) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value),
+                  static_cast<index_type>(__other.extents().extent(__rank_ - 1))),
+          "layout_right_padded::mapping from layout_right ctor: source stride must match the padded stride implied by "
+          "padding_value.");
+    }
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_right_padded::mapping from layout_right ctor: other.required_span_size() must be representable as "
+        "index_type.");
+  }
+
+  template <class _OtherExtents>
+    requires is_constructible_v<extents_type, _OtherExtents>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!(__rank_ == 0 && is_convertible_v<_OtherExtents, extents_type>))
+      mapping(const layout_stride::mapping<_OtherExtents>& __other)
+      : __extents_(extents_type(__other.extents())) {
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(__rank_ - 2) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value),
+                  static_cast<index_type>(__other.extents().extent(__rank_ - 1))),
+          "layout_right_padded::mapping from layout_stride ctor: source stride must match the padded stride implied by "
+          "padding_value.");
+
+    if constexpr (__rank_ > 0)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(__rank_ - 1) == 1,
+          "layout_right_padded::mapping from layout_stride ctor: stride(rank() - 1) must equal 1.");
+
+    if constexpr (__rank_ > 2) {
+      using _Common      = common_type_t<index_type, typename layout_stride::mapping<_OtherExtents>::index_type>;
+      _Common __expected = static_cast<_Common>(__other.stride(__rank_ - 2));
+      for (size_t __r = __rank_ - 2; __r-- > 0;) {
+        __expected *= static_cast<_Common>(__other.extents().extent(__r + 1));
+        _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+            static_cast<_Common>(__other.stride(__r)) == __expected,
+            "layout_right_padded::mapping from layout_stride ctor: strides are not "
+            "compatible with layout_right_padded.");
+      }
+    }
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_right_padded::mapping from layout_stride ctor: other.required_span_size() must be representable as "
+        "index_type.");
+
+    if constexpr (__rank_ > 1 && __static_padding_stride == dynamic_extent) {
+#  if 0 // TODO
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__is_representable_as<index_type>(__other.stride(__rank_ - 2)),
+          "layout_right_padded::mapping from layout_stride ctor: source padded stride must be representable as "
+          "index_type.");
+#  endif
+      __stride_rm2_ = __stride_rm2_type(static_cast<index_type>(__other.stride(__rank_ - 2)));
+    }
+  }
+
+  template <class _LayoutRightPaddedMapping>
+    requires __mdspan_detail::__layout_right_padded_mapping_of<_LayoutRightPaddedMapping> &&
+             is_constructible_v<extents_type, typename _LayoutRightPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutRightPaddedMapping::extents_type, extents_type> ||
+      (__rank_ > 1 && (padding_value != dynamic_extent || _LayoutRightPaddedMapping::padding_value == dynamic_extent)))
+      mapping(const _LayoutRightPaddedMapping& __other)
+      : __extents_(extents_type(__other.extents())) {
+    static_assert(
+        __rank_ <= 1 || padding_value == dynamic_extent || _LayoutRightPaddedMapping::padding_value == dynamic_extent ||
+            padding_value == _LayoutRightPaddedMapping::padding_value,
+        "layout_right_padded::mapping converting ctor: incompatible static padding values.");
+
+    if constexpr (__rank_ > 1 && padding_value != dynamic_extent)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(__rank_ - 2) ==
+              __mdspan_detail::__least_multiple_at_least(
+                  static_cast<index_type>(padding_value),
+                  static_cast<index_type>(__other.extents().extent(__rank_ - 1))),
+          "layout_right_padded::mapping from layout_right_padded ctor: source stride must match the padded stride "
+          "implied by padding_value.");
+
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_right_padded::mapping from layout_right_padded ctor: other.required_span_size() must be representable "
+        "as index_type.");
+
+    if constexpr (__rank_ > 1 && __static_padding_stride == dynamic_extent) {
+#  if 0 // TODO
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __mdspan_detail::__is_representable_as<index_type>(__other.stride(__rank_ - 2)),
+          "layout_right_padded::mapping from layout_right_padded ctor: source padded stride must be representable as "
+          "index_type.");
+#  endif
+      __stride_rm2_ = __stride_rm2_type(static_cast<index_type>(__other.stride(__rank_ - 2)));
+    }
+  }
+
+  template <class _LayoutLeftPaddedMapping>
+    requires(__mdspan_detail::__layout_left_padded_mapping_of<_LayoutLeftPaddedMapping> ||
+             __mdspan_detail::__layout_left_mapping_of<_LayoutLeftPaddedMapping>) &&
+            (__rank_ <= 1) && is_constructible_v<extents_type, typename _LayoutLeftPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutLeftPaddedMapping::extents_type, extents_type>)
+      mapping(const _LayoutLeftPaddedMapping& __other) noexcept
+      : __extents_(extents_type(__other.extents())) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_right_padded::mapping converting ctor: other.required_span_size() must be representable as "
+        "index_type.");
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr array<index_type, __rank_> strides() const noexcept {
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      return array<index_type, __rank_>{stride(_Pos)...};
+    }(make_index_sequence<__rank_>());
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept {
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      if (((__extents_.extent(_Pos) == static_cast<index_type>(0)) || ...))
+        return static_cast<index_type>(0);
+
+      return static_cast<index_type>(
+          (*this)(static_cast<index_type>(__extents_.extent(_Pos) - static_cast<index_type>(1))...) +
+          static_cast<index_type>(1));
+    }(make_index_sequence<__rank_>());
+  }
+
+  template <class... _Indices>
+    requires(sizeof...(_Indices) == __rank_) && (is_convertible_v<_Indices, index_type> && ...) &&
+            (is_nothrow_constructible_v<index_type, _Indices> && ...)
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
+                                 "layout_right_padded::mapping: out of bounds indexing.");
+    return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
+      return ((static_cast<index_type>(__idx) * stride(_Pos)) + ... + static_cast<index_type>(0));
+    }(make_index_sequence<sizeof...(_Indices)>());
+  }
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
+    if constexpr (__rank_ <= 1)
+      return true;
+    if constexpr (__last_static_extent == dynamic_extent || __static_padding_stride == dynamic_extent)
+      return false;
+    return __last_static_extent == __static_padding_stride;
+  }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const noexcept {
+    if constexpr (__rank_ <= 1)
+      return true;
+    return extents().extent(__rank_ - 1) == stride(__rank_ - 2);
+  }
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__r < __rank_, "layout_right_padded::mapping::stride(): invalid rank index.");
+
+    if constexpr (__rank_ == 0)
+      return static_cast<index_type>(1);
+
+    if (__r == __rank_ - 1)
+      return static_cast<index_type>(1);
+
+    if constexpr (__rank_ > 1) {
+      if (__r == __rank_ - 2)
+        return __stride_rm2();
+
+      index_type __stride = __stride_rm2();
+      for (rank_type __i = __rank_ - 2; __i > __r; --__i)
+        __stride *= __extents_.extent(__i);
+      return __stride;
+    }
+
+    return static_cast<index_type>(1);
+  }
+
+  template <class _LayoutRightPaddedMapping>
+    requires __mdspan_detail::__layout_right_padded_mapping_of<_LayoutRightPaddedMapping> &&
+             (_LayoutRightPaddedMapping::extents_type::rank() == __rank_)
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+  operator==(const mapping& __x, const _LayoutRightPaddedMapping& __y) noexcept {
+    return __x.extents() == __y.extents() && (__rank_ < 2 || __x.stride(__rank_ - 2) == __y.stride(__rank_ - 2));
+  }
+
+private:
+  _LIBCPP_NO_UNIQUE_ADDRESS __stride_rm2_type __stride_rm2_{};
+  _LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
+};
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___MDSPAN_LAYOUT_RIGHT_PADDED_H
diff --git a/libcxx/include/__mdspan/layout_stride.h b/libcxx/include/__mdspan/layout_stride.h
index eb22475756fde..769cc6c478cbe 100644
--- a/libcxx/include/__mdspan/layout_stride.h
+++ b/libcxx/include/__mdspan/layout_stride.h
@@ -21,6 +21,7 @@
 #include <__concepts/same_as.h>
 #include <__config>
 #include <__fwd/mdspan.h>
+#include <__mdspan/concepts.h>
 #include <__mdspan/extents.h>
 #include <__memory/addressof.h>
 #include <__type_traits/common_type.h>
@@ -47,24 +48,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 23
 
-namespace __mdspan_detail {
-template <class _Layout, class _Mapping>
-constexpr bool __is_mapping_of =
-    is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>;
-
-template <class _Mapping>
-concept __layout_mapping_alike = requires {
-  requires __is_mapping_of<typename _Mapping::layout_type, _Mapping>;
-  requires __is_extents_v<typename _Mapping::extents_type>;
-  { _Mapping::is_always_strided() } -> same_as<bool>;
-  { _Mapping::is_always_exhaustive() } -> same_as<bool>;
-  { _Mapping::is_always_unique() } -> same_as<bool>;
-  bool_constant<_Mapping::is_always_strided()>::value;
-  bool_constant<_Mapping::is_always_exhaustive()>::value;
-  bool_constant<_Mapping::is_always_unique()>::value;
-};
-} // namespace __mdspan_detail
-
 template <class _Extents>
 class layout_stride::mapping {
 public:
diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan
index 32468a128dc9a..0527524d6211b 100644
--- a/libcxx/include/mdspan
+++ b/libcxx/include/mdspan
@@ -255,6 +255,173 @@ namespace std {
   };
 }
 
+// layout_left_padded synopsis
+
+namespace std {
+  template<size_t PaddingValue>
+  template<class Extents>
+  class layout_left_padded<PaddingValue>::mapping {
+  public:
+    static constexpr size_t padding_value = PaddingValue;
+
+    using extents_type = Extents;
+    using index_type = extents_type::index_type;
+    using size_type = extents_type::size_type;
+    using rank_type = extents_type::rank_type;
+    using layout_type = layout_left_padded<PaddingValue>;
+
+  private:
+    static constexpr size_t rank_ = extents_type::rank();         // exposition only
+    static constexpr size_t first-static-extent =                 // exposition only
+      extents_type::static_extent(0);
+
+    // [mdspan.layout.leftpad.expo], exposition-only members
+    static constexpr size_t static-padding-stride = see below;  // exposition only
+
+  public:
+    // [mdspan.layout.leftpad.cons], constructors
+    constexpr mapping() noexcept : mapping(extents_type{}) {}
+    constexpr mapping(const mapping&) noexcept = default;
+    constexpr mapping(const extents_type&);
+    template<class OtherIndexType>
+      constexpr mapping(const extents_type&, OtherIndexType);
+    template<class OtherExtents>
+      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
+        mapping(const layout_left::mapping<OtherExtents>&);
+    template<class OtherExtents>
+      constexpr explicit(see below)
+        mapping(const layout_stride::mapping<OtherExtents>&);
+    template<class LayoutLeftPaddedMapping>
+      constexpr explicit(see below)
+        mapping(const LayoutLeftPaddedMapping&);
+    template<class LayoutRightPaddedMapping>
+      constexpr explicit(see below)
+        mapping(const LayoutRightPaddedMapping&) noexcept;
+
+    constexpr mapping& operator=(const mapping&) noexcept = default;
+
+    // [mdspan.layout.leftpad.obs], observers
+    constexpr const extents_type& extents() const noexcept { return extents_; }
+    constexpr array<index_type, rank_> strides() const noexcept;
+
+    constexpr index_type required_span_size() const noexcept;
+    template<class... Indices>
+      constexpr index_type operator()(Indices...) const noexcept;
+
+    static constexpr bool is_always_unique() noexcept { return true; }
+    static constexpr bool is_always_exhaustive() noexcept;
+    static constexpr bool is_always_strided() noexcept { return true; }
+
+    static constexpr bool is_unique() noexcept { return true; }
+    constexpr bool is_exhaustive() const noexcept;
+    static constexpr bool is_strided() noexcept { return true; }
+
+    constexpr index_type stride(rank_type) const noexcept;
+
+    template<class LayoutLeftPaddedMapping>
+      friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;
+
+  private:
+    // [mdspan.layout.leftpad.expo], exposition-only members
+    index_type stride-1 = static-padding-stride;                           // exposition only
+    extents_type extents_{};                                               // exposition only
+    // [mdspan.sub.map], submdspan mapping specialization
+    template<class... SliceSpecifiers>
+      constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const     // exposition only
+        -> see below;
+
+    template<class... SliceSpecifiers>
+      friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
+      return src.submdspan-mapping-impl(slices...);
+    }
+  };
+}
+
+// layout_right_padded synopsis
+
+namespace std {
+  template<size_t PaddingValue>
+  template<class Extents>
+  class layout_right_padded<PaddingValue>::mapping {
+  public:
+    static constexpr size_t padding_value = PaddingValue;
+
+    using extents_type = Extents;
+    using index_type = extents_type::index_type;
+    using size_type = extents_type::size_type;
+    using rank_type = extents_type::rank_type;
+    using layout_type = layout_right_padded<PaddingValue>;
+
+  private:
+    static constexpr size_t rank_ = extents_type::rank();    // exposition only
+    static constexpr size_t last-static-extent =             // exposition only
+      extents_type::static_extent(rank_ - 1);
+
+    // [mdspan.layout.rightpad.expo], exposition-only members
+    static constexpr size_t static-padding-stride = see below; // exposition only
+
+  public:
+    // [mdspan.layout.rightpad.cons], constructors
+    constexpr mapping() noexcept : mapping(extents_type{}) {}
+    constexpr mapping(const mapping&) noexcept = default;
+    constexpr mapping(const extents_type&);
+    template<class OtherIndexType>
+      constexpr mapping(const extents_type&, OtherIndexType);
+
+    template<class OtherExtents>
+      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
+        mapping(const layout_right::mapping<OtherExtents>&);
+    template<class OtherExtents>
+      constexpr explicit(see below)
+        mapping(const layout_stride::mapping<OtherExtents>&);
+    template<class LayoutRightPaddedMapping>
+      constexpr explicit(see below)
+        mapping(const LayoutRightPaddedMapping&);
+    template<class LayoutLeftPaddedMapping>
+      constexpr explicit(see below)
+        mapping(const LayoutLeftPaddedMapping&) noexcept;
+
+    constexpr mapping& operator=(const mapping&) noexcept = default;
+
+    // [mdspan.layout.rightpad.obs], observers
+    constexpr const extents_type& extents() const noexcept { return extents_; }
+    constexpr array<index_type, rank_> strides() const noexcept;
+
+    constexpr index_type required_span_size() const noexcept;
+
+    template<class... Indices>
+      constexpr index_type operator()(Indices...) const noexcept;
+
+    static constexpr bool is_always_unique() noexcept { return true; }
+    static constexpr bool is_always_exhaustive() noexcept;
+    static constexpr bool is_always_strided() noexcept { return true; }
+
+    static constexpr bool is_unique() noexcept { return true; }
+    constexpr bool is_exhaustive() const noexcept;
+    static constexpr bool is_strided() noexcept { return true; }
+
+    constexpr index_type stride(rank_type) const noexcept;
+
+    template<class LayoutRightPaddedMapping>
+      friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;
+
+  private:
+    // [mdspan.layout.rightpad.expo], exposition-only members
+    index_type stride-rm2 = static-padding-stride;                         // exposition only
+    extents_type extents_{};                                               // exposition only
+
+    // [mdspan.sub.map], submdspan mapping specialization
+    template<class... SliceSpecifiers>
+      constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const     // exposition only
+        -> see below;
+
+    template<class... SliceSpecifiers>
+      friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) {
+      return src.submdspan-mapping-impl(slices...);
+    }
+  };
+}
+
 // default_accessor synopsis
 
 namespace std {
@@ -458,6 +625,10 @@ namespace std {
 #    include <__mdspan/layout_right.h>
 #    include <__mdspan/layout_stride.h>
 #    include <__mdspan/mdspan.h>
+#    if _LIBCPP_STD_VER >= 26
+#      include <__mdspan/layout_left_padded.h>
+#      include <__mdspan/layout_right_padded.h>
+#    endif
 #  endif
 
 #  include <version>
diff --git a/libcxx/modules/std/mdspan.inc b/libcxx/modules/std/mdspan.inc
index c8cc78badb7d5..a9dea70b89a7a 100644
--- a/libcxx/modules/std/mdspan.inc
+++ b/libcxx/modules/std/mdspan.inc
@@ -25,6 +25,11 @@ export namespace std {
   using std::layout_right;
   using std::layout_stride;
 
+#  if _LIBCPP_STD_VER >= 26
+  using std::layout_left_padded;
+  using std::layout_right_padded;
+#  endif // _LIBCPP_STD_VER >= 26
+
   // [mdspan.accessor.default], class template default_accessor
   using std::default_accessor;
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/comparison.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/comparison.pass.cpp
new file mode 100644
index 0000000000000..ff85c44dcf61d
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/comparison.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutLeftPaddedMapping>
+// friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class LeftMapping, class RightMapping>
+constexpr void test_comparison(bool equal, const LeftMapping& left, const RightMapping& right) {
+  ASSERT_NOEXCEPT(left == right);
+  assert((left == right) == equal);
+  assert((left != right) == !equal);
+}
+
+struct DoesNotMatch {
+  constexpr bool does_not_match() const { return true; }
+};
+
+constexpr DoesNotMatch compare_layout_mappings(...) { return {}; }
+
+template <class LeftMapping, class RightMapping>
+constexpr auto compare_layout_mappings(const LeftMapping& left, const RightMapping& right) -> decltype(left == right) {
+  (void)left;
+  (void)right;
+  return true;
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using rank0_left  = std::layout_left_padded<0>::mapping<std::extents<size_t>>;
+    using rank0_right = std::layout_left_padded<4>::mapping<std::extents<size_t>>;
+    test_comparison(true, rank0_left(), rank0_right());
+  }
+
+  {
+    using rank1_fixed   = std::layout_left_padded<4>::mapping<std::extents<size_t, D>>;
+    using rank1_dynamic = std::layout_left_padded<D>::mapping<std::extents<size_t, 5>>;
+    test_comparison(true, rank1_fixed(std::extents<size_t, D>(5)), rank1_dynamic(std::extents<size_t, 5>(), 99));
+    test_comparison(false, rank1_fixed(std::extents<size_t, D>(3)), rank1_dynamic(std::extents<size_t, 5>(), 99));
+  }
+
+  {
+    using fixed_mapping   = std::layout_left_padded<4>::mapping<std::extents<size_t, 3, 7>>;
+    using dynamic_mapping = std::layout_left_padded<D>::mapping<std::extents<size_t, 3, 7>>;
+    test_comparison(true, fixed_mapping(), dynamic_mapping(std::extents<size_t, 3, 7>(), 4));
+    test_comparison(false, fixed_mapping(), dynamic_mapping(std::extents<size_t, 3, 7>(), 8));
+    test_comparison(false, fixed_mapping(), std::layout_left_padded<4>::mapping<std::extents<size_t, 3, 4>>());
+  }
+
+  {
+    using dynamic_mapping = std::layout_left_padded<D>::mapping<std::extents<size_t, D, 3>>;
+    test_comparison(
+        true, dynamic_mapping(std::extents<size_t, D, 3>(5), 5), dynamic_mapping(std::extents<size_t, D, 3>(5), 5));
+    test_comparison(
+        false, dynamic_mapping(std::extents<size_t, D, 3>(5), 5), dynamic_mapping(std::extents<size_t, D, 3>(5), 8));
+  }
+
+  static_assert(compare_layout_mappings(
+      std::layout_left_padded<4>::mapping<std::extents<int, D>>(std::extents<int, D>(5)),
+      std::layout_left_padded<4>::mapping<std::extents<int, 5>>()));
+  static_assert(compare_layout_mappings(std::layout_left_padded<4>::mapping<std::extents<int>>(),
+                                        std::layout_left_padded<4>::mapping<std::extents<int, 1>>())
+                    .does_not_match());
+  static_assert(compare_layout_mappings(std::layout_left_padded<4>::mapping<std::extents<int, 5, 7>>(),
+                                        std::layout_left_padded<4>::mapping<std::extents<int, 5>>())
+                    .does_not_match());
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
new file mode 100644
index 0000000000000..c7a2f622aef9e
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const mapping&) noexcept = default;
+// constexpr mapping& operator=(const mapping&) noexcept = default;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_copy_semantics(const Mapping& source) {
+  ASSERT_NOEXCEPT(Mapping(source));
+  static_assert(noexcept(std::declval<Mapping&>() = source));
+
+  Mapping copy(source);
+  assert(copy == source);
+
+  Mapping assigned;
+  assigned = source;
+  assert(assigned == source);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_copy_semantics(std::layout_left_padded<4>::mapping<std::extents<int32_t>>());
+  test_copy_semantics(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 5, 7>>(std::extents<int32_t, 5, 7>()));
+  test_copy_semantics(std::layout_left_padded<4>::mapping<std::extents<int8_t, D>>(std::extents<int8_t, D>(5)));
+  test_copy_semantics(std::layout_left_padded<4>::mapping<std::extents<uint8_t, D, 7>>(std::extents<uint8_t, D, 7>(5)));
+
+  test_copy_semantics(std::layout_left_padded<D>::mapping<std::extents<int32_t>>());
+  test_copy_semantics(std::layout_left_padded<D>::mapping<std::extents<uint32_t, 5, 7>>(std::extents<int32_t, 5, 7>()));
+  test_copy_semantics(std::layout_left_padded<D>::mapping<std::extents<int8_t, D>>(std::extents<int8_t, D>(5), 5));
+  test_copy_semantics(std::layout_left_padded<D>::mapping<std::extents<uint8_t, D, 7>>(std::extents<uint8_t, D, 7>(5)));
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
new file mode 100644
index 0000000000000..a36e548c72d0d
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping() noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_construction() {
+  using Extents = typename Mapping::extents_type;
+
+  ASSERT_NOEXCEPT(Mapping{});
+  Mapping mapping;
+  Mapping extents_mapping{Extents()};
+
+  assert(mapping == extents_mapping);
+  assert(mapping.extents() == Extents());
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_construction<std::layout_left_padded<4>::mapping<std::extents<int32_t>>>();
+  test_construction<std::layout_left_padded<4>::mapping<std::extents<int32_t, 1>>>();
+  test_construction<std::layout_left_padded<4>::mapping<std::extents<uint32_t, 2, 3>>>();
+  test_construction<std::layout_left_padded<4>::mapping<std::extents<uint32_t, 4, 5, D>>>();
+
+  test_construction<std::layout_left_padded<D>::mapping<std::extents<int32_t>>>();
+  test_construction<std::layout_left_padded<D>::mapping<std::extents<int32_t, 1>>>();
+  test_construction<std::layout_left_padded<D>::mapping<std::extents<uint32_t, 2, 3>>>();
+  test_construction<std::layout_left_padded<D>::mapping<std::extents<uint32_t, 4, 5, D>>>();
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
new file mode 100644
index 0000000000000..7bc4ffae3c25c
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const extents_type&);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+template <size_t PaddingValue, class Extents>
+constexpr void
+test_construction(Extents extents, std::array<typename Extents::index_type, Extents::rank()> expected_strides) {
+  using Mapping = typename std::layout_left_padded<PaddingValue>::template mapping<Extents>;
+  static_assert(Mapping::padding_value == PaddingValue);
+
+  Mapping mapping(extents);
+  assert(mapping.extents() == extents);
+
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_construction<4>(std::extents<int32_t>(),                  {});
+  test_construction<4>(std::extents<int32_t, 5>(),               {1});
+  test_construction<4>(std::extents<uint32_t, D>(7),             {1});
+  test_construction<4>(std::extents<uint32_t, 5, 7>(),           {1, 8});
+  test_construction<4>(std::extents<uint64_t, D, 2, 3>(6),       {1, 8, 16});
+  test_construction<D>(std::extents<int32_t>(),                  {});
+  test_construction<D>(std::extents<int32_t, 5>(),               {1});
+  test_construction<D>(std::extents<uint32_t, D>(7),             {1});
+  test_construction<D>(std::extents<uint32_t, 0, 7>(),           {1, 0});
+  test_construction<D>(std::extents<uint64_t, 5, 7>(),           {1, 5});
+  test_construction<D>(std::extents<uint64_t, D, 7>(5),          {1, 5});
+  test_construction<0>(std::extents<uint32_t, D, 13>(7),         {1, 7});
+  test_construction<0>(std::extents<uint32_t, 0, 7>(),           {1, 0});
+  //clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_left.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_left.pass.cpp
new file mode 100644
index 0000000000000..c9abe94b560d1
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_left.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class OtherExtents>
+// constexpr mapping(const layout_left::mapping<OtherExtents>& other);
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_left::mapping<std::extents<size_t>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src        = std::layout_left::mapping<std::extents<size_t, 4, 7>>;
+    using DstStatic  = std::layout_left_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    using DstDynamic = std::layout_left_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, DstStatic>(source);
+    test_conversion<true, DstDynamic>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right.pass.cpp
new file mode 100644
index 0000000000000..0e60913185d0d
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutRightMapping>
+// constexpr mapping(const LayoutRightMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_right::mapping<std::extents<size_t>>;
+    using Dst = std::layout_left_padded<D>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right_padded.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right_padded.pass.cpp
new file mode 100644
index 0000000000000..d3c017252db92
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_right_padded.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutRightPaddedMapping>
+// constexpr mapping(const LayoutRightPaddedMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t>>;
+    using Dst = std::layout_left_padded<D>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_stride.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_stride.pass.cpp
new file mode 100644
index 0000000000000..cceb073556761
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.layout_stride.pass.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class OtherExtents>
+// constexpr mapping(const layout_stride::mapping<OtherExtents>& other);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t>>;
+    using Dst = std::layout_left_padded<D>::mapping<std::extents<size_t>>;
+    Src source(std::extents<size_t>(), std::array<size_t, 0>{});
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, 3>>;
+    Src source(std::extents<size_t, 3>(), std::array<size_t, 1>{1});
+    test_conversion<false, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t, 5, 7>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, D, 7>>;
+    Src source(std::extents<size_t, 5, 7>(), std::array<size_t, 2>{1, 8});
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.assert.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.assert.pass.cpp
new file mode 100644
index 0000000000000..32de4a611da94
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.assert.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <mdspan>
+
+// constexpr mapping(const layout_stride::mapping<OtherExtents>& other);
+// constexpr mapping(const LayoutLeftPaddedMapping& other);
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <mdspan>
+
+#include "check_assertion.h"
+
+int main() {
+#if 0
+  {
+    using Src = std::layout_left_padded<std::dynamic_extent>::mapping<std::extents<uint32_t, 1, 0>>;
+    using Dst = std::layout_left_padded<std::dynamic_extent>::mapping<std::extents<uint8_t, 1, 0>>;
+
+    Src src(std::extents<uint32_t, 1, 0>(), 256);
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        Dst(src),
+        "layout_left_padded::mapping from layout_left_padded ctor: source padded stride must be "
+        "representable as index_type.");
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<uint32_t, 1, 0>>;
+    using Dst = std::layout_left_padded<std::dynamic_extent>::mapping<std::extents<uint8_t, 1, 0>>;
+
+    Src src(std::extents<uint32_t, 1, 0>(), std::array<uint32_t, 2>{1, 256});
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        Dst(src),
+        "layout_left_padded::mapping from layout_stride ctor: source padded stride must be "
+        "representable as index_type.");
+  }
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.pass.cpp
new file mode 100644
index 0000000000000..e020b7abdcffe
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.mapping.pass.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutLeftPaddedMapping>
+// constexpr mapping(const LayoutLeftPaddedMapping& other);
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+#if 0 // TODO
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+#endif
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_left_padded<D>::mapping<std::extents<size_t, 3>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t, 5, 7>>;
+    using Dst = std::layout_left_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    using Dst = std::layout_left_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    Src source(std::extents<size_t, D, 7>(4), 4);
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.padding.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.padding.pass.cpp
new file mode 100644
index 0000000000000..9dc2cd19453c7
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.padding.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const extents_type& e, index_type padding_stride);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+template <class Extents, class Padding>
+constexpr void test_construction(
+    Extents extents, Padding padding, std::array<typename Extents::index_type, Extents::rank()> expected_strides) {
+  using Mapping = std::layout_left_padded<std::dynamic_extent>::mapping<Extents>;
+  static_assert(Mapping::padding_value == std::dynamic_extent);
+
+  Mapping mapping(extents, padding);
+  assert(mapping.extents() == extents);
+
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_construction(std::extents<unsigned>(), 3,                   {});
+  test_construction(std::extents<unsigned, D>(7), 1337,            {1});
+  test_construction(std::extents<unsigned, D, 7>(5), 6,            {1, 6});
+  test_construction(std::extents<unsigned, 5, 7>(), 4,             {1, 8});
+  test_construction(std::extents<unsigned, D, 7, D>(7, 3), 4,      {1, 8, 56});
+  test_construction(std::extents<unsigned, 0, 7>(), 4,             {1, 0});
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
new file mode 100644
index 0000000000000..03e86d61050f9
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class Extents>
+// class layout_left_padded::mapping;
+
+#include <mdspan>
+
+void not_extents() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}layout_left_padded::mapping template argument must be a specialization of extents}}
+  [[maybe_unused]] std::layout_left_padded<4>::mapping<void> mapping;
+}
+
+void index_space_representable() {
+  // expected-error@*:* {{layout_left_padded::mapping index space for static extents must be representable as index_type.}}
+  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<signed char, 20, 20>> mapping;
+}
+
+void padding_stride_representable() {
+  // expected-error@*:* {{layout_left_padded::mapping padded stride for the first static extent must be representable as size_t and index_type.}}
+  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<signed char, 127, 1>> mapping;
+}
+
+void padded_product_representable() {
+  // expected-error@*:* {{layout_left_padded::mapping required span size for static extents must be representable as size_t and index_type.}}
+  [[maybe_unused]] std::layout_left_padded<64>::mapping<std::extents<signed char, 63, 2>> mapping;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/index_operator.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/index_operator.pass.cpp
new file mode 100644
index 0000000000000..ecbf147784d6b
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/index_operator.pass.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class... Indices>
+// constexpr index_type operator()(Indices...) const noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../ConvertibleToIntegral.h"
+
+template <class Mapping, class... Indices>
+concept operator_constraints = requires(Mapping mapping, Indices... idxs) {
+  { std::is_same_v<decltype(mapping(idxs...)), typename Mapping::index_type> };
+};
+
+template <class Mapping, class... Indices>
+  requires(operator_constraints<Mapping, Indices...>)
+constexpr bool check_operator_constraints(Mapping mapping, Indices... idxs) {
+  (void)mapping(idxs...);
+  return true;
+}
+
+template <class Mapping, class... Indices>
+constexpr bool check_operator_constraints(Mapping, Indices...) {
+  return false;
+}
+
+template <class Mapping, class... Args>
+constexpr void iterate_left_padded(Mapping mapping, typename Mapping::index_type expected, Args... args) {
+  constexpr int r = static_cast<int>(Mapping::extents_type::rank()) - 1 - static_cast<int>(sizeof...(Args));
+  if constexpr (-1 == r) {
+    ASSERT_NOEXCEPT(mapping(args...));
+    assert(expected == mapping(args...));
+  } else {
+    for (typename Mapping::index_type i = 0; i < mapping.extents().extent(r); ++i)
+      iterate_left_padded(
+          mapping, static_cast<typename Mapping::index_type>(expected + i * mapping.stride(r)), i, args...);
+  }
+}
+
+template <class Extents, size_t PaddingValue, class... Args>
+constexpr void test_iteration(Args... args) {
+  using Mapping = typename std::layout_left_padded<PaddingValue>::template mapping<Extents>;
+  Mapping mapping(Extents(args...));
+  iterate_left_padded(mapping, typename Extents::index_type(0));
+}
+
+template <class Mapping>
+constexpr void test_iteration(Mapping mapping) {
+  iterate_left_padded(mapping, typename Mapping::index_type(0));
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_iteration<std::extents<int>, 4>();
+  test_iteration<std::extents<unsigned, 7>, 4>();
+  test_iteration<std::extents<unsigned, 5, 7>, 4>();
+  test_iteration<std::extents<signed char, D, 2, 3>, 4>(3);
+
+  test_iteration<std::extents<int>, D>();
+  test_iteration<std::extents<unsigned, D>, D>(7);
+  test_iteration(std::layout_left_padded<D>::mapping<std::extents<unsigned, 5, 7>>(std::extents<unsigned, 5, 7>(), 6));
+  test_iteration(
+      std::layout_left_padded<D>::mapping<std::extents<unsigned, D, 2, 3>>(std::extents<unsigned, D, 2, 3>(3), 4));
+
+  // Check operator constraint for number of arguments
+  static_assert(check_operator_constraints(
+      std::layout_left_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), 0));
+  static_assert(!check_operator_constraints(
+      std::layout_left_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), 0, 0));
+
+  // Check operator constraint for convertibility of arguments to index_type
+  static_assert(check_operator_constraints(
+      std::layout_left_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), IntType(0)));
+  static_assert(!check_operator_constraints(
+      std::layout_left_padded<D>::mapping<std::extents<unsigned, D>>(std::extents<unsigned, D>(1), 1), IntType(0)));
+
+  // Check operator constraint for no-throw-constructibility of index_type from arguments
+  static_assert(!check_operator_constraints(
+      std::layout_left_padded<D>::mapping<std::extents<unsigned char, D>>(std::extents<unsigned char, D>(1), 1),
+      IntType(0)));
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
new file mode 100644
index 0000000000000..b77dcf99c4794
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// namespace std {
+//   template<class Extents>
+//   class layout_left_padded::mapping {
+//     ...
+//     static constexpr bool is_always_unique() noexcept;
+//     static constexpr bool is_always_exhaustive() noexcept;
+//     static constexpr bool is_always_strided() noexcept;
+//     static constexpr bool is_unique() noexcept;
+//     constexpr bool is_exhaustive() const noexcept;
+//     static constexpr bool is_strided() noexcept;
+//   };
+// }
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_properties(const Mapping& mapping, bool exhaustive, bool always_exhaustive) {
+  const Mapping const_mapping = mapping;
+
+  assert(Mapping::is_unique());
+  assert(mapping.is_unique());
+  assert(const_mapping.is_unique());
+
+  assert(mapping.is_exhaustive() == exhaustive);
+  assert(const_mapping.is_exhaustive() == exhaustive);
+
+  assert(Mapping::is_strided());
+  assert(mapping.is_strided());
+  assert(const_mapping.is_strided());
+
+  assert(Mapping::is_always_unique());
+  assert(Mapping::is_always_exhaustive() == always_exhaustive);
+  assert(Mapping::is_always_strided());
+
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_unique());
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_exhaustive());
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_strided());
+  ASSERT_NOEXCEPT(Mapping::is_always_unique());
+  ASSERT_NOEXCEPT(Mapping::is_always_exhaustive());
+  ASSERT_NOEXCEPT(Mapping::is_always_strided());
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<int32_t>>(),           true,   true);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<int32_t,  5>>(),       true,   true);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 3, 4>>(),    false,  false);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 4, 6>>(),    true,   true);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<int32_t,  D, 6>>(
+                                                      std::extents<int32_t,  D, 6>(7)),   false,  false);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<int32_t,  D, 6>>(
+                                                      std::extents<int32_t,  D, 6>(8)),   true,   false);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<uint32_t>>(),          true,   true);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 0, 6>>(),    true,   true);
+  test_properties(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 15, 0>>(),   false,  false);
+
+  test_properties(std::layout_left_padded<D>::mapping<std::extents<int32_t,  4, 6>>(
+                                                      std::extents<int32_t,  4, 6>(), 4), true,   false);
+  test_properties(std::layout_left_padded<D>::mapping<std::extents<int32_t,  6, 6>>(
+                                                      std::extents<int32_t,  6, 6>(), 4), false,  false);
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
new file mode 100644
index 0000000000000..8306c7bfd7e7a
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr index_type required_span_size() const noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_required_span_size(const Mapping& mapping, typename Mapping::index_type expected_size) {
+  ASSERT_NOEXCEPT(mapping.required_span_size());
+  assert(mapping.required_span_size() == expected_size);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<int32_t>>(),                                             1);
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<int32_t,  D>>(std::extents<int32_t,  D>(0)),             0);
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<uint32_t, D>>(std::extents<uint32_t, D>(7)),             7);
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 5,  7>>(),                                     53);
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<int64_t,  D,  2, 3>>(std::extents<int64_t, D, 2, 3>(7)), 47);
+  test_required_span_size(std::layout_left_padded<4>::mapping<std::extents<int64_t,  15, 0>>(),                                     0);
+
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<int32_t>>(),                                         1);
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<int32_t,  D>>(std::extents<int32_t,  D>(0)),         0);
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<uint32_t, D>>(std::extents<uint32_t, D>(7)),         7);
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<uint32_t, 5, 7>>(),                                  35);
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<int64_t,  5, 7>>(std::extents<int64_t, 5, 7>(), 6),  41);
+  test_required_span_size(std::layout_left_padded<D>::mapping<std::extents<int64_t,  0, 7>>(),                                  0);
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
new file mode 100644
index 0000000000000..82a9bb90e50f8
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+template <class Mapping, size_t... Indices>
+void test_mapping_requirements(std::index_sequence<Indices...>) {
+  using Extents = Mapping::extents_type;
+
+  LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v<Extents>);
+  static_assert(std::is_copy_constructible_v<Mapping>);
+  static_assert(std::is_nothrow_move_constructible_v<Mapping>);
+  static_assert(std::is_nothrow_move_assignable_v<Mapping>);
+  static_assert(std::is_nothrow_swappable_v<Mapping>);
+
+  ASSERT_SAME_TYPE(typename Mapping::index_type, typename Extents::index_type);
+  ASSERT_SAME_TYPE(typename Mapping::size_type, typename Extents::size_type);
+  ASSERT_SAME_TYPE(typename Mapping::rank_type, typename Extents::rank_type);
+  ASSERT_SAME_TYPE(typename Mapping::layout_type, std::layout_left_padded<Mapping::padding_value>);
+  ASSERT_SAME_TYPE(typename Mapping::layout_type::template mapping<Extents>, Mapping);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().extents()), const Extents&>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().strides()),
+                               std::array<typename Mapping::index_type, Extents::rank()>>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>()(Indices...)), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().required_span_size()), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_unique()), bool>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_exhaustive()), bool>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_strided()), bool>);
+  if constexpr (Extents::rank() > 0)
+    static_assert(std::is_same_v<decltype(std::declval<Mapping>().stride(0)), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_unique()), bool>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_exhaustive()), bool>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_strided()), bool>);
+}
+
+template <class Layout, class Extents>
+void test_layout_mapping_requirements() {
+  test_mapping_requirements<typename Layout::template mapping<Extents>>(std::make_index_sequence<Extents::rank()>());
+}
+
+int main() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_layout_mapping_requirements<std::layout_left_padded<4>, std::extents<int8_t>>();
+  test_layout_mapping_requirements<std::layout_left_padded<4>, std::extents<uint8_t, 4, 6>>();
+  test_layout_mapping_requirements<std::layout_left_padded<4>, std::extents<int32_t, D, 4>>();
+  test_layout_mapping_requirements<std::layout_left_padded<4>, std::extents<uint32_t, D, D>>();
+
+  test_layout_mapping_requirements<std::layout_left_padded<D>, std::extents<int8_t, 1, D, D>>();
+  test_layout_mapping_requirements<std::layout_left_padded<D>, std::extents<uint8_t, D, D, D>>();
+  test_layout_mapping_requirements<std::layout_left_padded<D>, std::extents<int32_t, D, D, D>>();
+  test_layout_mapping_requirements<std::layout_left_padded<D>, std::extents<uint32_t, D, D, D>>();
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/stride.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/stride.pass.cpp
new file mode 100644
index 0000000000000..8f6bea8145ba3
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/stride.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr index_type stride(rank_type) const noexcept;
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <typename Mapping>
+constexpr void test_stride(const Mapping& mapping,
+                           std::array<typename Mapping::index_type, Mapping::extents_type::rank()> expected_strides) {
+  ASSERT_NOEXCEPT(mapping.stride(0));
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_stride(std::layout_left_padded<4>::mapping<std::extents<int32_t,  D>>(
+                                                  std::extents<int32_t,  D>(7)),                    {1});
+  test_stride(std::layout_left_padded<4>::mapping<std::extents<int32_t,  7>>(),                     {1});
+  test_stride(std::layout_left_padded<4>::mapping<std::extents<uint32_t, 7, 8>>(),                  {1, 8});
+  test_stride(std::layout_left_padded<4>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                  std::extents<uint32_t, D, 8, D, D>(7, 9, 10)),    {1, 8, 64, 576});
+
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<int32_t,  D>>(
+                                                  std::extents<int32_t,  D>(7)),                    {1});
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<int32_t,  7>>(),                     {1});
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<uint32_t, 7, 8>>(),                  {1, 7});
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                  std::extents<uint32_t, D, 8, D, D>(7, 9, 10)),    {1, 7, 56, 504});
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<int32_t,  7, 8>>(
+                                                  std::extents<int32_t,  7, 8>(), 6),               {1, 12});
+  test_stride(std::layout_left_padded<D>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                  std::extents<uint32_t, D, 8, D, D>(7, 9, 10), 6), {1, 12, 96, 864});
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/comparison.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/comparison.pass.cpp
new file mode 100644
index 0000000000000..90d0a05d6a773
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/comparison.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutRightPaddedMapping>
+// friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class LeftMapping, class RightMapping>
+constexpr void test_comparison(bool equal, const LeftMapping& left, const RightMapping& right) {
+  ASSERT_NOEXCEPT(left == right);
+  assert((left == right) == equal);
+  assert((left != right) == !equal);
+}
+
+struct DoesNotMatch {
+  constexpr bool does_not_match() const { return true; }
+};
+
+constexpr DoesNotMatch compare_layout_mappings(...) { return {}; }
+
+template <class LeftMapping, class RightMapping>
+constexpr auto compare_layout_mappings(const LeftMapping& left, const RightMapping& right) -> decltype(left == right) {
+  (void)left;
+  (void)right;
+  return true;
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using rank0_left  = std::layout_right_padded<0>::mapping<std::extents<size_t>>;
+    using rank0_right = std::layout_right_padded<4>::mapping<std::extents<size_t>>;
+    test_comparison(true, rank0_left(), rank0_right());
+  }
+
+  {
+    using rank1_fixed   = std::layout_right_padded<4>::mapping<std::extents<size_t, D>>;
+    using rank1_dynamic = std::layout_right_padded<D>::mapping<std::extents<size_t, 5>>;
+    test_comparison(true, rank1_fixed(std::extents<size_t, D>(5)), rank1_dynamic(std::extents<size_t, 5>(), 99));
+    test_comparison(false, rank1_fixed(std::extents<size_t, D>(3)), rank1_dynamic(std::extents<size_t, 5>(), 99));
+  }
+
+  {
+    using fixed_mapping   = std::layout_right_padded<4>::mapping<std::extents<size_t, 3, 7>>;
+    using dynamic_mapping = std::layout_right_padded<D>::mapping<std::extents<size_t, 3, 7>>;
+    test_comparison(true, fixed_mapping(), dynamic_mapping(std::extents<size_t, 3, 7>(), 4));
+    test_comparison(false, fixed_mapping(), dynamic_mapping(std::extents<size_t, 3, 7>(), 6));
+    test_comparison(false, fixed_mapping(), std::layout_right_padded<4>::mapping<std::extents<size_t, 3, 4>>());
+  }
+
+  {
+    using dynamic_mapping = std::layout_right_padded<D>::mapping<std::extents<size_t, D, 3>>;
+    test_comparison(
+        true, dynamic_mapping(std::extents<size_t, D, 3>(5), 5), dynamic_mapping(std::extents<size_t, D, 3>(5), 5));
+    test_comparison(
+        false, dynamic_mapping(std::extents<size_t, D, 3>(5), 5), dynamic_mapping(std::extents<size_t, D, 3>(5), 8));
+  }
+
+  static_assert(compare_layout_mappings(
+      std::layout_right_padded<4>::mapping<std::extents<int, D>>(std::extents<int, D>(5)),
+      std::layout_right_padded<4>::mapping<std::extents<int, 5>>()));
+  static_assert(compare_layout_mappings(std::layout_right_padded<4>::mapping<std::extents<int>>(),
+                                        std::layout_right_padded<4>::mapping<std::extents<int, 1>>())
+                    .does_not_match());
+  static_assert(compare_layout_mappings(std::layout_right_padded<4>::mapping<std::extents<int, 5, 7>>(),
+                                        std::layout_right_padded<4>::mapping<std::extents<int, 5>>())
+                    .does_not_match());
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
new file mode 100644
index 0000000000000..8bdc53ee4e32b
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const mapping&) noexcept = default;
+// constexpr mapping& operator=(const mapping&) noexcept = default;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_copy_semantics(const Mapping& source) {
+  ASSERT_NOEXCEPT(Mapping(source));
+  static_assert(noexcept(std::declval<Mapping&>() = source));
+
+  Mapping copy(source);
+  assert(copy == source);
+
+  Mapping assigned;
+  assigned = source;
+  assert(assigned == source);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_copy_semantics(std::layout_right_padded<4>::mapping<std::extents<int32_t>>());
+  test_copy_semantics(
+      std::layout_right_padded<4>::mapping<std::extents<uint32_t, 5, 7>>(std::extents<int32_t, 5, 7>()));
+  test_copy_semantics(std::layout_right_padded<4>::mapping<std::extents<int8_t, D>>(std::extents<int8_t, D>(5)));
+  test_copy_semantics(
+      std::layout_right_padded<4>::mapping<std::extents<uint8_t, D, 7>>(std::extents<uint8_t, D, 7>(5)));
+
+  test_copy_semantics(std::layout_right_padded<D>::mapping<std::extents<int32_t>>());
+  test_copy_semantics(
+      std::layout_right_padded<D>::mapping<std::extents<uint32_t, 5, 7>>(std::extents<int32_t, 5, 7>()));
+  test_copy_semantics(std::layout_right_padded<D>::mapping<std::extents<int8_t, D>>(std::extents<int8_t, D>(5), 5));
+  test_copy_semantics(
+      std::layout_right_padded<D>::mapping<std::extents<uint8_t, D, 7>>(std::extents<uint8_t, D, 7>(5)));
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
new file mode 100644
index 0000000000000..73e6dc3288337
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping() noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_construction() {
+  using Extents = typename Mapping::extents_type;
+
+  ASSERT_NOEXCEPT(Mapping{});
+  Mapping mapping;
+  Mapping extents_mapping{Extents()};
+
+  assert(mapping == extents_mapping);
+  assert(mapping.extents() == Extents());
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_construction<std::layout_right_padded<4>::mapping<std::extents<int32_t>>>();
+  test_construction<std::layout_right_padded<4>::mapping<std::extents<int32_t, 1>>>();
+  test_construction<std::layout_right_padded<4>::mapping<std::extents<uint32_t, 2, 3>>>();
+  test_construction<std::layout_right_padded<4>::mapping<std::extents<uint32_t, 4, 5, D>>>();
+
+  test_construction<std::layout_right_padded<D>::mapping<std::extents<int32_t>>>();
+  test_construction<std::layout_right_padded<D>::mapping<std::extents<int32_t, 1>>>();
+  test_construction<std::layout_right_padded<D>::mapping<std::extents<uint32_t, 2, 3>>>();
+  test_construction<std::layout_right_padded<D>::mapping<std::extents<uint32_t, 4, 5, D>>>();
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
new file mode 100644
index 0000000000000..6526b54b963f9
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const extents_type&);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+template <size_t PaddingValue, class Extents>
+constexpr void
+test_construction(Extents extents, std::array<typename Extents::index_type, Extents::rank()> expected_strides) {
+  using Mapping = typename std::layout_right_padded<PaddingValue>::template mapping<Extents>;
+  static_assert(Mapping::padding_value == PaddingValue);
+
+  Mapping mapping(extents);
+  assert(mapping.extents() == extents);
+
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_construction<4>(std::extents<int32_t>(),                  {});
+  test_construction<4>(std::extents<int32_t, 5>(),               {1});
+  test_construction<4>(std::extents<uint32_t, D>(7),             {1});
+  test_construction<4>(std::extents<uint32_t, 5, 7>(),           {8, 1});
+  test_construction<4>(std::extents<uint64_t, D, 2, 3>(6),       {8, 4, 1});
+  test_construction<D>(std::extents<int32_t>(),                  {});
+  test_construction<D>(std::extents<int32_t, 5>(),               {1});
+  test_construction<D>(std::extents<uint32_t, D>(7),             {1});
+  test_construction<D>(std::extents<uint32_t, 0, 7>(),           {7, 1});
+  test_construction<D>(std::extents<uint64_t, 5, 7>(),           {7, 1});
+  test_construction<D>(std::extents<uint64_t, D, 7>(5),          {7, 1});
+  test_construction<0>(std::extents<uint32_t, D, 13>(7),         {13, 1});
+  test_construction<0>(std::extents<uint32_t, 0, 7>(),           {7, 1});
+  //clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left.pass.cpp
new file mode 100644
index 0000000000000..c9d1a23c286ce
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutLeftMapping>
+// constexpr mapping(const LayoutLeftMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_left::mapping<std::extents<size_t>>;
+    using Dst = std::layout_right_padded<D>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left_padded.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left_padded.pass.cpp
new file mode 100644
index 0000000000000..c1da8426273bd
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_left_padded.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutLeftPaddedMapping>
+// constexpr mapping(const LayoutLeftPaddedMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t>>;
+    using Dst = std::layout_right_padded<D>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_right.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_right.pass.cpp
new file mode 100644
index 0000000000000..7bbbb52d0394f
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_right.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class OtherExtents>
+// constexpr mapping(const layout_right::mapping<OtherExtents>& other);
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_right::mapping<std::extents<size_t>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src        = std::layout_right::mapping<std::extents<size_t, 4, 8>>;
+    using DstStatic  = std::layout_right_padded<4>::mapping<std::extents<size_t, 4, 8>>;
+    using DstDynamic = std::layout_right_padded<D>::mapping<std::extents<size_t, D, 8>>;
+    Src source;
+    test_conversion<true, DstStatic>(source);
+    test_conversion<true, DstDynamic>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_stride.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_stride.pass.cpp
new file mode 100644
index 0000000000000..ef84dfbc61e8e
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.layout_stride.pass.cpp
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class OtherExtents>
+// constexpr mapping(const layout_stride::mapping<OtherExtents>& other);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t>>;
+    using Dst = std::layout_right_padded<D>::mapping<std::extents<size_t>>;
+    Src source(std::extents<size_t>(), std::array<size_t, 0>{});
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, 3>>;
+    Src source(std::extents<size_t, 3>(), std::array<size_t, 1>{1});
+    test_conversion<false, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<size_t, 5, 7>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, D, 7>>;
+    Src source(std::extents<size_t, 5, 7>(), std::array<size_t, 2>{8, 1});
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.assert.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.assert.pass.cpp
new file mode 100644
index 0000000000000..87d2dffb6010d
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.assert.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <mdspan>
+
+// constexpr mapping(const layout_stride::mapping<OtherExtents>& other);
+// constexpr mapping(const LayoutRightPaddedMapping& other);
+
+#include <array>
+#include <cstddef>
+#include <mdspan>
+
+#include "check_assertion.h"
+
+int main() {
+#if 0
+  {
+    using Src = std::layout_right_padded<std::dynamic_extent>::mapping<std::extents<uint32_t, 0, 1>>;
+    using Dst = std::layout_right_padded<std::dynamic_extent>::mapping<std::extents<uint8_t, 0, 1>>;
+
+    Src src(std::extents<uint32_t, 0, 1>(), 256);
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        Dst(src),
+        "layout_right_padded::mapping from layout_right_padded ctor: source padded stride must be "
+        "representable as index_type.");
+  }
+
+  {
+    using Src = std::layout_stride::mapping<std::extents<uint32_t, 0, 1>>;
+    using Dst = std::layout_right_padded<std::dynamic_extent>::mapping<std::extents<uint8_t, 0, 1>>;
+
+    Src src(std::extents<uint32_t, 0, 1>(), std::array<uint32_t, 2>{256, 1});
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        Dst(src),
+        "layout_right_padded::mapping from layout_stride ctor: source padded stride must be "
+        "representable as index_type.");
+  }
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.pass.cpp
new file mode 100644
index 0000000000000..66fd8a48b712b
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.mapping.pass.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutRightPaddedMapping>
+// constexpr mapping(const LayoutRightPaddedMapping& other);
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+#if 0 // TODO
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+#endif
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t, 3>>;
+    using Dst = std::layout_right_padded<D>::mapping<std::extents<size_t, 3>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t, 5, 7>>;
+    using Dst = std::layout_right_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    using Dst = std::layout_right_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    Src source(std::extents<size_t, D, 7>(4), 4);
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.padding.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.padding.pass.cpp
new file mode 100644
index 0000000000000..f016b54cfabbe
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.padding.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr mapping(const extents_type& e, index_type padding_stride);
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+template <class Extents, class Padding>
+constexpr void test_construction(
+    Extents extents, Padding padding, std::array<typename Extents::index_type, Extents::rank()> expected_strides) {
+  using Mapping = std::layout_right_padded<std::dynamic_extent>::mapping<Extents>;
+  static_assert(Mapping::padding_value == std::dynamic_extent);
+
+  Mapping mapping(extents, padding);
+  assert(mapping.extents() == extents);
+
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_construction(std::extents<unsigned>(), 3,                   {});
+  test_construction(std::extents<unsigned, D>(7), 1337,            {1});
+  test_construction(std::extents<unsigned, D, 7>(5), 6,            {12, 1});
+  test_construction(std::extents<unsigned, 5, 7>(), 4,             {8, 1});
+  test_construction(std::extents<unsigned, D, 7, D>(7, 3), 4,      {28, 4, 1});
+  test_construction(std::extents<unsigned, 0, 7>(), 4,             {8, 1});
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
new file mode 100644
index 0000000000000..370d8e1b453e4
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class Extents>
+// class layout_right_padded::mapping;
+
+#include <mdspan>
+
+void not_extents() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}layout_right_padded::mapping template argument must be a specialization of extents}}
+  [[maybe_unused]] std::layout_right_padded<4>::mapping<void> mapping;
+}
+
+void index_space_representable() {
+  // expected-error@*:* {{layout_right_padded::mapping index space for static extents must be representable as index_type.}}
+  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<signed char, 20, 20>> mapping;
+}
+
+void padding_stride_representable() {
+  // expected-error@*:* {{layout_right_padded::mapping padded stride for the last static extent must be representable as size_t and index_type.}}
+  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<signed char, 0, 127>> mapping;
+}
+
+void padded_product_representable() {
+  // expected-error@*:* {{layout_right_padded::mapping required span size for static extents must be representable as size_t and index_type.}}
+  [[maybe_unused]] std::layout_right_padded<64>::mapping<std::extents<signed char, 2, 63>> mapping;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/index_operator.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/index_operator.pass.cpp
new file mode 100644
index 0000000000000..5dd9275049a0c
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/index_operator.pass.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class... Indices>
+// constexpr index_type operator()(Indices...) const noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../ConvertibleToIntegral.h"
+
+template <class Mapping, class... Indices>
+concept operator_constraints = requires(Mapping mapping, Indices... idxs) {
+  { std::is_same_v<decltype(mapping(idxs...)), typename Mapping::index_type> };
+};
+
+template <class Mapping, class... Indices>
+  requires(operator_constraints<Mapping, Indices...>)
+constexpr bool check_operator_constraints(Mapping mapping, Indices... idxs) {
+  (void)mapping(idxs...);
+  return true;
+}
+
+template <class Mapping, class... Indices>
+constexpr bool check_operator_constraints(Mapping, Indices...) {
+  return false;
+}
+
+template <class Mapping, class... Args>
+constexpr void iterate_right_padded(Mapping mapping, typename Mapping::index_type expected, Args... args) {
+  constexpr size_t r = sizeof...(Args);
+  if constexpr (Mapping::extents_type::rank() == r) {
+    ASSERT_NOEXCEPT(mapping(args...));
+    assert(expected == mapping(args...));
+  } else {
+    for (typename Mapping::index_type i = 0; i < mapping.extents().extent(r); ++i)
+      iterate_right_padded(
+          mapping, static_cast<typename Mapping::index_type>(expected + i * mapping.stride(r)), args..., i);
+  }
+}
+
+template <class Extents, size_t PaddingValue, class... Args>
+constexpr void test_iteration(Args... args) {
+  using Mapping = typename std::layout_right_padded<PaddingValue>::template mapping<Extents>;
+  Mapping mapping(Extents(args...));
+  iterate_right_padded(mapping, typename Extents::index_type(0));
+}
+
+template <class Mapping>
+constexpr void test_iteration(Mapping mapping) {
+  iterate_right_padded(mapping, typename Mapping::index_type(0));
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_iteration<std::extents<int>, 4>();
+  test_iteration<std::extents<unsigned, 7>, 4>();
+  test_iteration<std::extents<unsigned, 5, 7>, 4>();
+  test_iteration<std::extents<signed char, D, 2, 3>, 4>(3);
+
+  test_iteration<std::extents<int>, D>();
+  test_iteration<std::extents<unsigned, D>, D>(7);
+  test_iteration(std::layout_right_padded<D>::mapping<std::extents<unsigned, 5, 7>>(std::extents<unsigned, 5, 7>(), 6));
+  test_iteration(
+      std::layout_right_padded<D>::mapping<std::extents<unsigned, D, 2, 3>>(std::extents<unsigned, D, 2, 3>(3), 4));
+
+  // Check operator constraint for number of arguments
+  static_assert(check_operator_constraints(
+      std::layout_right_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), 0));
+  static_assert(!check_operator_constraints(
+      std::layout_right_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), 0, 0));
+
+  // Check operator constraint for convertibility of arguments to index_type
+  static_assert(check_operator_constraints(
+      std::layout_right_padded<D>::mapping<std::extents<int, D>>(std::extents<int, D>(1), 1), IntType(0)));
+  static_assert(!check_operator_constraints(
+      std::layout_right_padded<D>::mapping<std::extents<unsigned, D>>(std::extents<unsigned, D>(1), 1), IntType(0)));
+
+  // Check operator constraint for no-throw-constructibility of index_type from arguments
+  static_assert(!check_operator_constraints(
+      std::layout_right_padded<D>::mapping<std::extents<unsigned char, D>>(std::extents<unsigned char, D>(1), 1),
+      IntType(0)));
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
new file mode 100644
index 0000000000000..0adaab5c4d14c
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// namespace std {
+//   template<class Extents>
+//   class layout_right_padded::mapping {
+//     ...
+//     static constexpr bool is_always_unique() noexcept;
+//     static constexpr bool is_always_exhaustive() noexcept;
+//     static constexpr bool is_always_strided() noexcept;
+//     static constexpr bool is_unique() noexcept;
+//     constexpr bool is_exhaustive() const noexcept;
+//     static constexpr bool is_strided() noexcept;
+//   };
+// }
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_properties(const Mapping& mapping, bool exhaustive, bool always_exhaustive) {
+  const Mapping const_mapping = mapping;
+
+  assert(Mapping::is_unique());
+  assert(mapping.is_unique());
+  assert(const_mapping.is_unique());
+
+  assert(mapping.is_exhaustive() == exhaustive);
+  assert(const_mapping.is_exhaustive() == exhaustive);
+
+  assert(Mapping::is_strided());
+  assert(mapping.is_strided());
+  assert(const_mapping.is_strided());
+
+  assert(Mapping::is_always_unique());
+  assert(Mapping::is_always_exhaustive() == always_exhaustive);
+  assert(Mapping::is_always_strided());
+
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_unique());
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_exhaustive());
+  ASSERT_NOEXCEPT(std::declval<Mapping>().is_strided());
+  ASSERT_NOEXCEPT(Mapping::is_always_unique());
+  ASSERT_NOEXCEPT(Mapping::is_always_exhaustive());
+  ASSERT_NOEXCEPT(Mapping::is_always_strided());
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<int32_t>>(),           true,   true);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<int32_t,  5>>(),       true,   true);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<uint32_t, 3, 4>>(),    true,   true);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<uint32_t, 4, 6>>(),    false,  false);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<int32_t,  6, D>>(
+                                                       std::extents<int32_t,  6, D>(7)),   false,  false);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<int32_t,  6, D>>(
+                                                       std::extents<int32_t,  6, D>(8)),   true,   false);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<uint32_t>>(),          true,   true);
+  test_properties(std::layout_right_padded<4>::mapping<std::extents<uint32_t, 0, 6>>(),    false,  false);
+
+  test_properties(std::layout_right_padded<D>::mapping<std::extents<int32_t,  6, D>>(
+                                                       std::extents<int32_t,  6, D>(4), 4), true,   false);
+  test_properties(std::layout_right_padded<D>::mapping<std::extents<int32_t,  6, D>>(
+                                                       std::extents<int32_t,  6, D>(6), 4), false,  false);
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
new file mode 100644
index 0000000000000..e4289707d5702
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr index_type required_span_size() const noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_required_span_size(const Mapping& mapping, typename Mapping::index_type expected_size) {
+  ASSERT_NOEXCEPT(mapping.required_span_size());
+  assert(mapping.required_span_size() == expected_size);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<int32_t>>(),                                              1);
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<int32_t,  D>>(std::extents<int32_t,  D>(0)),              0);
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<uint32_t, D>>(std::extents<uint32_t, D>(7)),              7);
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<uint32_t, 5,  7>>(),                                      39);
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<int64_t,  D,  2, 3>>(std::extents<int64_t, D, 2, 3>(7)),  55);
+  test_required_span_size(std::layout_right_padded<4>::mapping<std::extents<int64_t,  15, 0>>(),                                      0);
+
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<int32_t>>(),                                          1);
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<int32_t,  D>>(std::extents<int32_t,  D>(0)),          0);
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<uint32_t, D>>(std::extents<uint32_t, D>(7)),          7);
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<uint32_t, 5, 7>>(),                                   35);
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<int64_t,  5, 7>>(std::extents<int64_t, 5, 7>(), 6),   55);
+  test_required_span_size(std::layout_right_padded<D>::mapping<std::extents<int64_t,  0, 7>>(),                                   0);
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
new file mode 100644
index 0000000000000..033ffce606911
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+template <class Mapping, size_t... Indices>
+void test_mapping_requirements(std::index_sequence<Indices...>) {
+  using Extents = Mapping::extents_type;
+
+  LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v<Extents>);
+  static_assert(std::is_copy_constructible_v<Mapping>);
+  static_assert(std::is_nothrow_move_constructible_v<Mapping>);
+  static_assert(std::is_nothrow_move_assignable_v<Mapping>);
+  static_assert(std::is_nothrow_swappable_v<Mapping>);
+
+  ASSERT_SAME_TYPE(typename Mapping::index_type, typename Extents::index_type);
+  ASSERT_SAME_TYPE(typename Mapping::size_type, typename Extents::size_type);
+  ASSERT_SAME_TYPE(typename Mapping::rank_type, typename Extents::rank_type);
+  ASSERT_SAME_TYPE(typename Mapping::layout_type, std::layout_right_padded<Mapping::padding_value>);
+  ASSERT_SAME_TYPE(typename Mapping::layout_type::template mapping<Extents>, Mapping);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().extents()), const Extents&>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().strides()),
+                               std::array<typename Mapping::index_type, Extents::rank()>>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>()(Indices...)), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().required_span_size()), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_unique()), bool>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_exhaustive()), bool>);
+  static_assert(std::is_same_v<decltype(std::declval<Mapping>().is_strided()), bool>);
+  if constexpr (Extents::rank() > 0)
+    static_assert(std::is_same_v<decltype(std::declval<Mapping>().stride(0)), typename Mapping::index_type>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_unique()), bool>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_exhaustive()), bool>);
+  static_assert(std::is_same_v<decltype(Mapping::is_always_strided()), bool>);
+}
+
+template <class Layout, class Extents>
+void test_layout_mapping_requirements() {
+  test_mapping_requirements<typename Layout::template mapping<Extents>>(std::make_index_sequence<Extents::rank()>());
+}
+
+int main() {
+  constexpr size_t D = std::dynamic_extent;
+
+  test_layout_mapping_requirements<std::layout_right_padded<4>, std::extents<int8_t>>();
+  test_layout_mapping_requirements<std::layout_right_padded<4>, std::extents<uint8_t, 4, 6>>();
+  test_layout_mapping_requirements<std::layout_right_padded<4>, std::extents<int32_t, D, 4>>();
+  test_layout_mapping_requirements<std::layout_right_padded<4>, std::extents<uint32_t, D, D>>();
+
+  test_layout_mapping_requirements<std::layout_right_padded<D>, std::extents<int8_t, 1, D, D>>();
+  test_layout_mapping_requirements<std::layout_right_padded<D>, std::extents<uint8_t, D, D, D>>();
+  test_layout_mapping_requirements<std::layout_right_padded<D>, std::extents<int32_t, D, D, D>>();
+  test_layout_mapping_requirements<std::layout_right_padded<D>, std::extents<uint32_t, D, D, D>>();
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/stride.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/stride.pass.cpp
new file mode 100644
index 0000000000000..ea65fd104d918
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/stride.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// constexpr index_type stride(rank_type) const noexcept;
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <mdspan>
+
+#include "test_macros.h"
+
+template <class Mapping>
+constexpr void test_stride(const Mapping& mapping,
+                           std::array<typename Mapping::index_type, Mapping::extents_type::rank()> expected_strides) {
+  ASSERT_NOEXCEPT(mapping.stride(0));
+  for (typename Mapping::rank_type r = 0; r < Mapping::extents_type::rank(); ++r)
+    assert(mapping.stride(r) == expected_strides[r]);
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  // clang-format off
+  test_stride(std::layout_right_padded<4>::mapping<std::extents<int32_t,  D>>(
+                                                   std::extents<int32_t,  D>(7)),                    {1});
+  test_stride(std::layout_right_padded<4>::mapping<std::extents<int32_t,  7>>(),                     {1});
+  test_stride(std::layout_right_padded<4>::mapping<std::extents<uint32_t, 7, 8>>(),                  {8, 1});
+  test_stride(std::layout_right_padded<4>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                   std::extents<uint32_t, D, 8, D, D>(7, 9, 10)),    {864, 108, 12, 1});
+
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<int32_t,  D>>(
+                                                   std::extents<int32_t,  D>(7)),                    {1});
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<int32_t,  7>>(),                     {1});
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<uint32_t, 7, 8>>(),                  {8, 1});
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                   std::extents<uint32_t, D, 8, D, D>(7, 9, 10)),    {720, 90, 10, 1});
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<int32_t,  7, 8>>(
+                                                   std::extents<int32_t,  7, 8>(), 6),               {12, 1});
+  test_stride(std::layout_right_padded<D>::mapping<std::extents<uint32_t, D, 8, D, D>>(
+                                                   std::extents<uint32_t, D, 8, D, D>(7, 9, 10), 6), {864, 108, 12, 1});
+  // clang-format on
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}

>From 6454dce6db5efe0e6c0a5262132fa476647c04ab Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sat, 21 Mar 2026 23:41:50 +0800
Subject: [PATCH 2/6] impl

---
 libcxx/include/CMakeLists.txt                 |  3 +-
 libcxx/include/__mdspan/concepts.h            | 46 ---------
 ...layout_padded_common.h => layout_common.h} | 55 ++++++++++-
 libcxx/include/__mdspan/layout_left.h         | 29 ++++++
 libcxx/include/__mdspan/layout_left_padded.h  | 12 +--
 libcxx/include/__mdspan/layout_right.h        | 31 ++++++
 libcxx/include/__mdspan/layout_right_padded.h | 13 +--
 libcxx/include/__mdspan/layout_stride.h       | 18 ++--
 libcxx/include/mdspan                         | 74 +++++++++++---
 .../ctor.layout_left_padded.pass.cpp          | 97 +++++++++++++++++++
 .../ctor.layout_right_padded.pass.cpp         | 97 +++++++++++++++++++
 11 files changed, 381 insertions(+), 94 deletions(-)
 delete mode 100644 libcxx/include/__mdspan/concepts.h
 rename libcxx/include/__mdspan/{layout_padded_common.h => layout_common.h} (60%)
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_left/ctor.layout_left_padded.pass.cpp
 create mode 100644 libcxx/test/std/containers/views/mdspan/layout_right/ctor.layout_right_padded.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 474f21bc4959d..3a6061099c74d 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -572,12 +572,11 @@ set(files
   __math/trigonometric_functions.h
   __mbstate_t.h
   __mdspan/aligned_accessor.h
-  __mdspan/concepts.h
   __mdspan/default_accessor.h
   __mdspan/extents.h
   __mdspan/layout_left.h
   __mdspan/layout_left_padded.h
-  __mdspan/layout_padded_common.h
+  __mdspan/layout_common.h
   __mdspan/layout_right_padded.h
   __mdspan/layout_right.h
   __mdspan/layout_stride.h
diff --git a/libcxx/include/__mdspan/concepts.h b/libcxx/include/__mdspan/concepts.h
deleted file mode 100644
index 9b5d321c79cdb..0000000000000
--- a/libcxx/include/__mdspan/concepts.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef _LIBCPP___MDSPAN_CONCEPT_H
-#define _LIBCPP___MDSPAN_CONCEPT_H
-
-#include <__assert>
-#include <__concepts/same_as.h>
-#include <__config>
-#include <__mdspan/extents.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-#if _LIBCPP_STD_VER >= 23
-
-namespace __mdspan_detail {
-  
-template <class _Layout, class _Mapping>
-constexpr bool __is_mapping_of =
-    is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>;
-
-template <class _Mapping>
-concept __layout_mapping_alike = requires {
-  requires __is_mapping_of<typename _Mapping::layout_type, _Mapping>;
-  requires __is_extents_v<typename _Mapping::extents_type>;
-  { _Mapping::is_always_strided() } -> same_as<bool>;
-  { _Mapping::is_always_exhaustive() } -> same_as<bool>;
-  { _Mapping::is_always_unique() } -> same_as<bool>;
-  bool_constant<_Mapping::is_always_strided()>::value;
-  bool_constant<_Mapping::is_always_exhaustive()>::value;
-  bool_constant<_Mapping::is_always_unique()>::value;
-};
-
-} // namespace __mdspan_detail
-
-#endif // _LIBCPP_STD_VER >= 23
-
-_LIBCPP_END_NAMESPACE_STD
-
-_LIBCPP_POP_MACROS
-
-#endif // _LIBCPP___MDSPAN_CONCEPT_H
diff --git a/libcxx/include/__mdspan/layout_padded_common.h b/libcxx/include/__mdspan/layout_common.h
similarity index 60%
rename from libcxx/include/__mdspan/layout_padded_common.h
rename to libcxx/include/__mdspan/layout_common.h
index aae860f6f8d87..77ad5a0f4e6b4 100644
--- a/libcxx/include/__mdspan/layout_padded_common.h
+++ b/libcxx/include/__mdspan/layout_common.h
@@ -14,12 +14,12 @@
 //
 //===---------------------------------------------------------------------===//
 
-#ifndef _LIBCPP___MDSPAN_LAYOUT_PADDED_COMMON_H
-#define _LIBCPP___MDSPAN_LAYOUT_PADDED_COMMON_H
+#ifndef _LIBCPP___MDSPAN_LAYOUT_COMMON_H
+#define _LIBCPP___MDSPAN_LAYOUT_COMMON_H
 
 #include <__config>
 #include <__fwd/mdspan.h>
-#include <__mdspan/concepts.h>
+#include <__mdspan/extents.h>
 #include <__memory/addressof.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -31,10 +31,28 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER >= 26
+#if _LIBCPP_STD_VER >= 23
 
 namespace __mdspan_detail {
 
+template <class _Layout, class _Mapping>
+constexpr bool __is_mapping_of =
+    is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>;
+
+template <class _Mapping>
+concept __layout_mapping_alike = requires {
+  requires __is_mapping_of<typename _Mapping::layout_type, _Mapping>;
+  requires __is_extents_v<typename _Mapping::extents_type>;
+  { _Mapping::is_always_strided() } -> same_as<bool>;
+  { _Mapping::is_always_exhaustive() } -> same_as<bool>;
+  { _Mapping::is_always_unique() } -> same_as<bool>;
+  bool_constant<_Mapping::is_always_strided()>::value;
+  bool_constant<_Mapping::is_always_exhaustive()>::value;
+  bool_constant<_Mapping::is_always_unique()>::value;
+};
+
+#  if _LIBCPP_STD_VER >= 26
+
 template <class _Integral>
 _LIBCPP_HIDE_FROM_ABI constexpr _Integral __least_multiple_at_least(_Integral __multiplier, _Integral __minimum) {
   if (__multiplier == static_cast<_Integral>(0))
@@ -87,9 +105,36 @@ concept __layout_right_mapping_of = __layout_mapping_alike<_Mapping> && __is_map
 template <class _Mapping>
 concept __layout_left_mapping_of = __layout_mapping_alike<_Mapping> && __is_mapping_of<layout_left, _Mapping>;
 
+_LIBCPP_HIDE_FROM_ABI constexpr size_t
+__compute_static_padding_stride(size_t __rank, size_t __padding_value, size_t __static_extent) {
+  if (__rank <= 1)
+    return 0uz;
+  if (__padding_value == dynamic_extent || __static_extent == dynamic_extent)
+    return dynamic_extent;
+  return __least_multiple_at_least(__padding_value, __static_extent);
+}
+
+template <class _Mapping>
+  requires __layout_left_padded_mapping_of<_Mapping> || __layout_right_padded_mapping_of<_Mapping>
+constexpr size_t __static_padding_stride_of = [] {
+  using _Extents          = _Mapping::extents_type;
+  constexpr size_t __rank = _Extents::rank();
+
+  if constexpr (__layout_left_padded_mapping_of<_Mapping>) {
+    constexpr size_t __static_extent = __rank == 0 ? 0 : _Extents::static_extent(0);
+    return __compute_static_padding_stride(__rank, _Mapping::padding_value, __static_extent);
+  }
+  if constexpr (__layout_right_padded_mapping_of<_Mapping>) {
+    constexpr size_t __static_extent = __rank == 0 ? 0 : _Extents::static_extent(__rank - 1);
+    return __compute_static_padding_stride(__rank, _Mapping::padding_value, __static_extent);
+  }
+}();
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 } // namespace __mdspan_detail
 
-#endif // _LIBCPP_STD_VER >= 26
+#endif // _LIBCPP_STD_VER >= 23
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__mdspan/layout_left.h b/libcxx/include/__mdspan/layout_left.h
index 2f515afb6c860..6eff932067d49 100644
--- a/libcxx/include/__mdspan/layout_left.h
+++ b/libcxx/include/__mdspan/layout_left.h
@@ -21,6 +21,7 @@
 #include <__config>
 #include <__fwd/mdspan.h>
 #include <__mdspan/extents.h>
+#include <__mdspan/layout_common.h>
 #include <__memory/addressof.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/is_constructible.h>
@@ -109,6 +110,34 @@ class layout_left::mapping {
         "layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
   }
 
+#  if _LIBCPP_STD_VER >= 26 // _LIBCPP_STD_VER >= 26
+
+  template <class _LayoutLeftPaddedMapping>
+    requires __mdspan_detail::__layout_left_padded_mapping_of<_LayoutLeftPaddedMapping> &&
+             is_constructible_v<extents_type, typename _LayoutLeftPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutLeftPaddedMapping::extents_type, extents_type>)
+      mapping(const _LayoutLeftPaddedMapping& __other) noexcept
+      : __extents_(__other.extents()) {
+    static_assert(
+        _Extents::rank() <= 1 || _Extents::static_extent(0) == dynamic_extent ||
+            __mdspan_detail::__static_padding_stride_of<_LayoutLeftPaddedMapping> == dynamic_extent ||
+            _Extents::static_extent(0) == __mdspan_detail::__static_padding_stride_of<_LayoutLeftPaddedMapping>,
+        "layout_left::mapping converting from layout_left_padded ctor: incompatible static extent(0) and "
+        "source static padding stride.");
+
+    if constexpr (extents_type::rank() > 1)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(1) == __other.extents().extent(0),
+          "layout_left::mapping from layout_left_padded ctor: other.stride(1) must equal other.extents().extent(0).");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_left::mapping from layout_left_padded ctor: other.required_span_size() must be representable as "
+        "index_type.");
+  }
+
+#  endif // _LIBCPP_STD_VER >= 26
+
   template <class _OtherExtents>
     requires(is_constructible_v<extents_type, _OtherExtents>)
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(extents_type::rank() > 0)
diff --git a/libcxx/include/__mdspan/layout_left_padded.h b/libcxx/include/__mdspan/layout_left_padded.h
index f2709975c49bf..1888fcd5cf691 100644
--- a/libcxx/include/__mdspan/layout_left_padded.h
+++ b/libcxx/include/__mdspan/layout_left_padded.h
@@ -20,10 +20,9 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
-#include <__mdspan/concepts.h>
 #include <__mdspan/extents.h>
+#include <__mdspan/layout_common.h>
 #include <__mdspan/layout_left.h>
-#include <__mdspan/layout_padded_common.h>
 #include <__mdspan/layout_right.h>
 #include <__mdspan/layout_stride.h>
 #include <__memory/addressof.h>
@@ -64,13 +63,8 @@ class layout_left_padded<_PaddingValue>::mapping {
   static constexpr rank_type __rank_            = extents_type::rank();
   static constexpr size_t __first_static_extent = __rank_ == 0 ? 0uz : extents_type::static_extent(0);
 
-  static constexpr size_t __static_padding_stride = [] {
-    if constexpr (__rank_ <= 1)
-      return 0uz;
-    if constexpr (padding_value == dynamic_extent || __first_static_extent == dynamic_extent)
-      return dynamic_extent;
-    return __mdspan_detail::__least_multiple_at_least(padding_value, __first_static_extent);
-  }();
+  static constexpr size_t __static_padding_stride =
+      __mdspan_detail::__compute_static_padding_stride(__rank_, padding_value, __first_static_extent);
 
   // Do not store value if __static_padding_stride is not dynamic_extent.
   using __stride_1_type = std::extents<index_type, __static_padding_stride>;
diff --git a/libcxx/include/__mdspan/layout_right.h b/libcxx/include/__mdspan/layout_right.h
index ccfbd23e28ad7..36f376cd4cf98 100644
--- a/libcxx/include/__mdspan/layout_right.h
+++ b/libcxx/include/__mdspan/layout_right.h
@@ -22,6 +22,7 @@
 #include <__cstddef/size_t.h>
 #include <__fwd/mdspan.h>
 #include <__mdspan/extents.h>
+#include <__mdspan/layout_common.h>
 #include <__memory/addressof.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/is_constructible.h>
@@ -109,6 +110,36 @@ class layout_right::mapping {
         "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
   }
 
+#  if _LIBCPP_STD_VER >= 26 // _LIBCPP_STD_VER >= 26
+
+  template <class _LayoutRightPaddedMapping>
+    requires __mdspan_detail::__layout_right_padded_mapping_of<_LayoutRightPaddedMapping> &&
+             is_constructible_v<extents_type, typename _LayoutRightPaddedMapping::extents_type>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
+      !is_convertible_v<typename _LayoutRightPaddedMapping::extents_type, extents_type>)
+      mapping(const _LayoutRightPaddedMapping& __other) noexcept
+      : __extents_(__other.extents()) {
+    static_assert(
+        extents_type::rank() <= 1 || extents_type::static_extent(extents_type::rank() - 1) == dynamic_extent ||
+            __mdspan_detail::__static_padding_stride_of<_LayoutRightPaddedMapping> == dynamic_extent ||
+            extents_type::static_extent(extents_type::rank() - 1) ==
+                __mdspan_detail::__static_padding_stride_of<_LayoutRightPaddedMapping>,
+        "layout_right::mapping converting from layout_right_padded ctor: incompatible static "
+        "extent(extents_type::rank() - 1) and source static padding stride.");
+
+    if constexpr (extents_type::rank() > 1)
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __other.stride(extents_type::rank() - 2) == __other.extents().extent(extents_type::rank() - 1),
+          "layout_right::mapping from layout_right_padded ctor: other.stride(rank() - 2) must equal "
+          "other.extents().extent(rank() - 1).");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
+        "layout_right::mapping from layout_right_padded ctor: other.required_span_size() must be representable as "
+        "index_type.");
+  }
+
+#  endif // _LIBCPP_STD_VER >= 26
+
   template <class _OtherExtents>
     requires(is_constructible_v<extents_type, _OtherExtents>)
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(extents_type::rank() > 0)
diff --git a/libcxx/include/__mdspan/layout_right_padded.h b/libcxx/include/__mdspan/layout_right_padded.h
index 2d89722536ba2..9b479d0b34bef 100644
--- a/libcxx/include/__mdspan/layout_right_padded.h
+++ b/libcxx/include/__mdspan/layout_right_padded.h
@@ -20,10 +20,9 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
-#include <__mdspan/concepts.h>
 #include <__mdspan/extents.h>
+#include <__mdspan/layout_common.h>
 #include <__mdspan/layout_left.h>
-#include <__mdspan/layout_padded_common.h>
 #include <__mdspan/layout_right.h>
 #include <__mdspan/layout_stride.h>
 #include <__memory/addressof.h>
@@ -64,14 +63,10 @@ class layout_right_padded<_PaddingValue>::mapping {
   static constexpr rank_type __rank_           = extents_type::rank();
   static constexpr size_t __last_static_extent = __rank_ == 0 ? 0uz : extents_type::static_extent(__rank_ - 1);
 
-  static constexpr size_t __static_padding_stride = [] {
-    if constexpr (__rank_ <= 1)
-      return 0uz;
-    if constexpr (padding_value == dynamic_extent || __last_static_extent == dynamic_extent)
-      return dynamic_extent;
-    return __mdspan_detail::__least_multiple_at_least(padding_value, __last_static_extent);
-  }();
+  static constexpr size_t __static_padding_stride =
+      __mdspan_detail::__compute_static_padding_stride(__rank_, padding_value, __last_static_extent);
 
+  // Do not store value if __static_padding_stride is not dynamic_extent.
   using __stride_rm2_type = std::extents<index_type, __static_padding_stride>;
 
   _LIBCPP_HIDE_FROM_ABI static constexpr bool __index_space_size_is_representable(const extents_type& __ext) {
diff --git a/libcxx/include/__mdspan/layout_stride.h b/libcxx/include/__mdspan/layout_stride.h
index 769cc6c478cbe..892a88571bd99 100644
--- a/libcxx/include/__mdspan/layout_stride.h
+++ b/libcxx/include/__mdspan/layout_stride.h
@@ -21,8 +21,8 @@
 #include <__concepts/same_as.h>
 #include <__config>
 #include <__fwd/mdspan.h>
-#include <__mdspan/concepts.h>
 #include <__mdspan/extents.h>
+#include <__mdspan/layout_common.h>
 #include <__memory/addressof.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/is_constructible.h>
@@ -207,12 +207,16 @@ class layout_stride::mapping {
     requires(__mdspan_detail::__layout_mapping_alike<_StridedLayoutMapping> &&
              is_constructible_v<extents_type, typename _StridedLayoutMapping::extents_type> &&
              _StridedLayoutMapping::is_always_unique() && _StridedLayoutMapping::is_always_strided())
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(
-      !(is_convertible_v<typename _StridedLayoutMapping::extents_type, extents_type> &&
-        (__mdspan_detail::__is_mapping_of<layout_left, _StridedLayoutMapping> ||
-         __mdspan_detail::__is_mapping_of<layout_right, _StridedLayoutMapping> ||
-         __mdspan_detail::__is_mapping_of<layout_stride, _StridedLayoutMapping>)))
-      mapping(const _StridedLayoutMapping& __other) noexcept
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!(
+      is_convertible_v<typename _StridedLayoutMapping::extents_type, extents_type> &&
+      (__mdspan_detail::__is_mapping_of<layout_left, _StridedLayoutMapping> ||
+       __mdspan_detail::__is_mapping_of<layout_right, _StridedLayoutMapping> ||
+       __mdspan_detail::__is_mapping_of<layout_stride, _StridedLayoutMapping>
+#  if _LIBCPP_STD_VER >= 26
+       || __mdspan_detail::__layout_left_padded_mapping_of<_StridedLayoutMapping> ||
+       __mdspan_detail::__layout_right_padded_mapping_of<_StridedLayoutMapping>
+#  endif
+       ))) mapping(const _StridedLayoutMapping& __other) noexcept
       : __extents_(__other.extents()), __strides_([&]<size_t... _Pos>(index_sequence<_Pos...>) {
           // stride() only compiles for rank > 0
           if constexpr (__rank_ > 0) {
diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan
index 0527524d6211b..19114c8b380e5 100644
--- a/libcxx/include/mdspan
+++ b/libcxx/include/mdspan
@@ -97,12 +97,12 @@ namespace std {
   class layout_left::mapping {
   public:
     using extents_type = Extents;
-    using index_type = typename extents_type::index_type;
-    using size_type = typename extents_type::size_type;
-    using rank_type = typename extents_type::rank_type;
+    using index_type = extents_type::index_type;
+    using size_type = extents_type::size_type;
+    using rank_type = extents_type::rank_type;
     using layout_type = layout_left;
 
-    // [mdspan.layout.right.cons], constructors
+    // [mdspan.layout.left.cons], constructors
     constexpr mapping() noexcept = default;
     constexpr mapping(const mapping&) noexcept = default;
     constexpr mapping(const extents_type&) noexcept;
@@ -112,13 +112,17 @@ namespace std {
     template<class OtherExtents>
       constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
         mapping(const layout_right::mapping<OtherExtents>&) noexcept;
+    template<class LayoutLeftPaddedMapping>
+      constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type,
+                                           extents_type>)
+        mapping(const LayoutLeftPaddedMapping&) noexcept;
     template<class OtherExtents>
-      constexpr explicit(extents_type::rank() > 0)
-        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
+      constexpr explicit(see below)
+        mapping(const layout_stride::mapping<OtherExtents>&);
 
     constexpr mapping& operator=(const mapping&) noexcept = default;
 
-    // [mdspan.layout.right.obs], observers
+    // [mdspan.layout.left.obs], observers
     constexpr const extents_type& extents() const noexcept { return extents_; }
 
     constexpr index_type required_span_size() const noexcept;
@@ -140,7 +144,18 @@ namespace std {
       friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
 
   private:
-    extents_type extents_{};    // exposition only
+    extents_type extents_{};                                               // exposition only
+
+    // [mdspan.sub.map], submdspan mapping specialization
+    template<class... SliceSpecifiers>
+      constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const     // exposition only
+        -> see below;
+
+    template<class... SliceSpecifiers>
+      friend constexpr auto submdspan_mapping(
+        const mapping& src, SliceSpecifiers... slices) {
+          return src.submdspan-mapping-impl(slices...);
+      }
   };
 }
 
@@ -151,9 +166,9 @@ namespace std {
   class layout_right::mapping {
   public:
     using extents_type = Extents;
-    using index_type = typename extents_type::index_type;
-    using size_type = typename extents_type::size_type;
-    using rank_type = typename extents_type::rank_type;
+    using index_type = extents_type::index_type;
+    using size_type = extents_type::size_type;
+    using rank_type = extents_type::rank_type;
     using layout_type = layout_right;
 
     // [mdspan.layout.right.cons], constructors
@@ -166,8 +181,12 @@ namespace std {
     template<class OtherExtents>
       constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
         mapping(const layout_left::mapping<OtherExtents>&) noexcept;
+    template<class LayoutRightPaddedMapping>
+      constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type,
+                                           extents_type>)
+        mapping(const LayoutRightPaddedMapping&) noexcept;
     template<class OtherExtents>
-      constexpr explicit(extents_type::rank() > 0)
+      constexpr explicit(see below)
         mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
 
     constexpr mapping& operator=(const mapping&) noexcept = default;
@@ -195,19 +214,31 @@ namespace std {
 
   private:
     extents_type extents_{};    // exposition only
+
+    // [mdspan.sub.map], submdspan mapping specialization
+    template<class... SliceSpecifiers>
+      constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const       // exposition only
+        -> see below;
+
+    template<class... SliceSpecifiers>
+      friend constexpr auto submdspan_mapping(
+        const mapping& src, SliceSpecifiers... slices) {
+          return src.submdspan-mapping-impl(slices...);
+      }
   };
 }
 
 // layout_stride synopsis
 
+layout_stride provides a layout mapping where the strides are user-defined.
 namespace std {
   template<class Extents>
   class layout_stride::mapping {
   public:
     using extents_type = Extents;
-    using index_type = typename extents_type::index_type;
-    using size_type = typename extents_type::size_type;
-    using rank_type = typename extents_type::rank_type;
+    using index_type = extents_type::index_type;
+    using size_type = extents_type::size_type;
+    using rank_type = extents_type::rank_type;
     using layout_type = layout_stride;
 
   private:
@@ -237,7 +268,7 @@ namespace std {
       constexpr index_type operator()(Indices...) const noexcept;
 
     static constexpr bool is_always_unique() noexcept { return true; }
-    static constexpr bool is_always_exhaustive() noexcept { return false; }
+    static constexpr bool is_always_exhaustive() noexcept;
     static constexpr bool is_always_strided() noexcept { return true; }
 
     static constexpr bool is_unique() noexcept { return true; }
@@ -252,6 +283,17 @@ namespace std {
   private:
     extents_type extents_{};                    // exposition only
     array<index_type, rank_> strides_{};        // exposition only
+
+    // [mdspan.sub.map], submdspan mapping specialization
+    template<class... SliceSpecifiers>
+      constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const       // exposition only
+        -> see below;
+
+    template<class... SliceSpecifiers>
+      friend constexpr auto submdspan_mapping(
+        const mapping& src, SliceSpecifiers... slices) {
+          return src.submdspan-mapping-impl(slices...);
+      }
   };
 }
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left/ctor.layout_left_padded.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left/ctor.layout_left_padded.pass.cpp
new file mode 100644
index 0000000000000..581639011b46a
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_left/ctor.layout_left_padded.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutLeftPaddedMapping>
+// constexpr mapping(const LayoutLeftPaddedMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t>>;
+    using Dst = std::layout_left::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<4>::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_left::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src        = std::layout_left_padded<4>::mapping<std::extents<size_t, 4, 7>>;
+    using DstStatic  = std::layout_left::mapping<std::extents<size_t, 4, 7>>;
+    using DstDynamic = std::layout_left::mapping<std::extents<size_t, D, 7>>;
+    Src source;
+    test_conversion<true, DstStatic>(source);
+    test_conversion<true, DstDynamic>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<D>::mapping<std::extents<size_t, D, D>>;
+    using Dst = std::layout_left::mapping<std::extents<size_t, D, D>>;
+    Src source(std::extents<size_t, D, D>(7, 4), 7);
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_left_padded<D>::mapping<std::extents<size_t, D, 7>>;
+    using Dst = std::layout_left::mapping<std::extents<size_t, 4, 7>>;
+    Src source(std::extents<size_t, D, 7>(4), 4);
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right/ctor.layout_right_padded.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right/ctor.layout_right_padded.pass.cpp
new file mode 100644
index 0000000000000..7ba04806d9829
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/layout_right/ctor.layout_right_padded.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <mdspan>
+
+// template<class LayoutRightPaddedMapping>
+// constexpr mapping(const LayoutRightPaddedMapping& other) noexcept;
+
+#include <cassert>
+#include <cstddef>
+#include <mdspan>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <class Dst, class Src>
+constexpr void assert_same_mapping(const Dst& dst, const Src& src) {
+  assert(dst.extents() == src.extents());
+
+  if constexpr (Dst::extents_type::rank() > 0) {
+    for (typename Dst::rank_type r = 0; r < Dst::extents_type::rank(); ++r)
+      assert(dst.stride(r) == static_cast<typename Dst::index_type>(src.stride(r)));
+  }
+}
+
+template <bool Implicit, class Dst, class Src>
+constexpr void test_conversion(const Src& source) {
+  static_assert(std::is_constructible_v<Dst, Src>);
+
+  ASSERT_NOEXCEPT(Dst(source));
+
+  Dst direct(source);
+  assert_same_mapping(direct, source);
+
+  if constexpr (Implicit) {
+    Dst implicit = source;
+    assert_same_mapping(implicit, source);
+  } else {
+    static_assert(!std::is_convertible_v<Src, Dst>);
+  }
+}
+
+constexpr bool test() {
+  constexpr size_t D = std::dynamic_extent;
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t>>;
+    using Dst = std::layout_right::mapping<std::extents<size_t>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<4>::mapping<std::extents<size_t, 5>>;
+    using Dst = std::layout_right::mapping<std::extents<size_t, D>>;
+    Src source;
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src        = std::layout_right_padded<4>::mapping<std::extents<size_t, 4, 8>>;
+    using DstStatic  = std::layout_right::mapping<std::extents<size_t, 4, 8>>;
+    using DstDynamic = std::layout_right::mapping<std::extents<size_t, D, 8>>;
+    Src source;
+    test_conversion<true, DstStatic>(source);
+    test_conversion<true, DstDynamic>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<D>::mapping<std::extents<size_t, D, D>>;
+    using Dst = std::layout_right::mapping<std::extents<size_t, D, D>>;
+    Src source(std::extents<size_t, D, D>(4, 7), 7);
+    test_conversion<true, Dst>(source);
+  }
+
+  {
+    using Src = std::layout_right_padded<D>::mapping<std::extents<size_t, D, 8>>;
+    using Dst = std::layout_right::mapping<std::extents<size_t, 4, 8>>;
+    Src source(std::extents<size_t, D, 8>(4), 4);
+    test_conversion<false, Dst>(source);
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+  return 0;
+}

>From 3eba8b93bf41ee27c008eb58a77822563f168e08 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 22 Mar 2026 02:06:23 +0800
Subject: [PATCH 3/6] fix CI

---
 libcxx/include/CMakeLists.txt      |  4 ++--
 libcxx/include/module.modulemap.in | 17 ++++++++++-------
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 3a6061099c74d..163b6afd0b7cf 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -574,11 +574,11 @@ set(files
   __mdspan/aligned_accessor.h
   __mdspan/default_accessor.h
   __mdspan/extents.h
+  __mdspan/layout_common.h
   __mdspan/layout_left.h
   __mdspan/layout_left_padded.h
-  __mdspan/layout_common.h
-  __mdspan/layout_right_padded.h
   __mdspan/layout_right.h
+  __mdspan/layout_right_padded.h
   __mdspan/layout_stride.h
   __mdspan/mdspan.h
   __memory/addressof.h
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index d6e8289b7c8b0..dec1f8fe95191 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1632,13 +1632,16 @@ module std [system] {
   }
 
   module mdspan {
-    module aligned_accessor   { header "__mdspan/aligned_accessor.h" }
-    module default_accessor   { header "__mdspan/default_accessor.h" }
-    module extents            { header "__mdspan/extents.h" }
-    module fwd                { header "__fwd/mdspan.h" }
-    module layout_left        { header "__mdspan/layout_left.h" }
-    module layout_right       { header "__mdspan/layout_right.h" }
-    module layout_stride      { header "__mdspan/layout_stride.h" }
+    module aligned_accessor     { header "__mdspan/aligned_accessor.h" }
+    module default_accessor     { header "__mdspan/default_accessor.h" }
+    module extents              { header "__mdspan/extents.h" }
+    module fwd                  { header "__fwd/mdspan.h" }
+    module layout_common        { header "__mdspan/layout_common.h" }
+    module layout_left          { header "__mdspan/layout_left.h" }
+    module layout_left_padded   { header "__mdspan/layout_left_padded.h" }
+    module layout_right         { header "__mdspan/layout_right.h" }
+    module layout_right_padded  { header "__mdspan/layout_right_padded.h" }
+    module layout_stride        { header "__mdspan/layout_stride.h" }
     module mdspan {
       header "__mdspan/mdspan.h"
       export std.array // returned by some methods

>From ce389876f6297d02b0042ea2bd5c8d701e8404d7 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 22 Mar 2026 02:26:32 +0800
Subject: [PATCH 4/6] fix CI

---
 libcxx/include/__fwd/mdspan.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__fwd/mdspan.h b/libcxx/include/__fwd/mdspan.h
index 8c069577ab2a9..ea3fac58fe974 100644
--- a/libcxx/include/__fwd/mdspan.h
+++ b/libcxx/include/__fwd/mdspan.h
@@ -18,8 +18,8 @@
 #define _LIBCPP___MDSPAN_LAYOUTS_H
 
 #include <__config>
-#include <cstddef>
-#include <span>
+#include <__cstddef/size_t.h>
+#include <__fwd/span.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header

>From bc4dec6a4d9943f71952f5f6fd0af8cded9dba8f Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 22 Mar 2026 18:19:29 +0800
Subject: [PATCH 5/6] fix CI

---
 libcxx/include/__mdspan/layout_common.h                      | 5 +++++
 libcxx/include/__mdspan/layout_left.h                        | 1 +
 libcxx/include/__mdspan/layout_left_padded.h                 | 1 +
 libcxx/include/__mdspan/layout_right.h                       | 1 +
 libcxx/include/__mdspan/layout_right_padded.h                | 1 +
 .../views/mdspan/layout_left_padded/ctor.copy.pass.cpp       | 2 ++
 .../views/mdspan/layout_left_padded/ctor.default.pass.cpp    | 1 +
 .../views/mdspan/layout_left_padded/ctor.extents.pass.cpp    | 1 +
 .../views/mdspan/layout_left_padded/properties.pass.cpp      | 2 ++
 .../mdspan/layout_left_padded/required_span_size.pass.cpp    | 1 +
 .../mdspan/layout_left_padded/static_requirements.pass.cpp   | 1 +
 .../views/mdspan/layout_right_padded/ctor.copy.pass.cpp      | 2 ++
 .../views/mdspan/layout_right_padded/ctor.default.pass.cpp   | 1 +
 .../views/mdspan/layout_right_padded/ctor.extents.pass.cpp   | 1 +
 .../views/mdspan/layout_right_padded/properties.pass.cpp     | 2 ++
 .../mdspan/layout_right_padded/required_span_size.pass.cpp   | 1 +
 .../mdspan/layout_right_padded/static_requirements.pass.cpp  | 1 +
 17 files changed, 25 insertions(+)

diff --git a/libcxx/include/__mdspan/layout_common.h b/libcxx/include/__mdspan/layout_common.h
index 77ad5a0f4e6b4..56748e6343cc4 100644
--- a/libcxx/include/__mdspan/layout_common.h
+++ b/libcxx/include/__mdspan/layout_common.h
@@ -17,10 +17,15 @@
 #ifndef _LIBCPP___MDSPAN_LAYOUT_COMMON_H
 #define _LIBCPP___MDSPAN_LAYOUT_COMMON_H
 
+#include <__concepts/same_as.h>
 #include <__config>
+#include <__cstddef/size_t.h>
 #include <__fwd/mdspan.h>
+#include <__fwd/span.h>
 #include <__mdspan/extents.h>
 #include <__memory/addressof.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_same.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
diff --git a/libcxx/include/__mdspan/layout_left.h b/libcxx/include/__mdspan/layout_left.h
index 6eff932067d49..84ab647bd0792 100644
--- a/libcxx/include/__mdspan/layout_left.h
+++ b/libcxx/include/__mdspan/layout_left.h
@@ -20,6 +20,7 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
+#include <__fwd/span.h>
 #include <__mdspan/extents.h>
 #include <__mdspan/layout_common.h>
 #include <__memory/addressof.h>
diff --git a/libcxx/include/__mdspan/layout_left_padded.h b/libcxx/include/__mdspan/layout_left_padded.h
index 1888fcd5cf691..aedffd917f098 100644
--- a/libcxx/include/__mdspan/layout_left_padded.h
+++ b/libcxx/include/__mdspan/layout_left_padded.h
@@ -20,6 +20,7 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
+#include <__fwd/span.h>
 #include <__mdspan/extents.h>
 #include <__mdspan/layout_common.h>
 #include <__mdspan/layout_left.h>
diff --git a/libcxx/include/__mdspan/layout_right.h b/libcxx/include/__mdspan/layout_right.h
index 36f376cd4cf98..7e3df54658258 100644
--- a/libcxx/include/__mdspan/layout_right.h
+++ b/libcxx/include/__mdspan/layout_right.h
@@ -21,6 +21,7 @@
 #include <__config>
 #include <__cstddef/size_t.h>
 #include <__fwd/mdspan.h>
+#include <__fwd/span.h>
 #include <__mdspan/extents.h>
 #include <__mdspan/layout_common.h>
 #include <__memory/addressof.h>
diff --git a/libcxx/include/__mdspan/layout_right_padded.h b/libcxx/include/__mdspan/layout_right_padded.h
index 9b479d0b34bef..f6a34972de453 100644
--- a/libcxx/include/__mdspan/layout_right_padded.h
+++ b/libcxx/include/__mdspan/layout_right_padded.h
@@ -20,6 +20,7 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
+#include <__fwd/span.h>
 #include <__mdspan/extents.h>
 #include <__mdspan/layout_common.h>
 #include <__mdspan/layout_left.h>
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
index c7a2f622aef9e..ca5b5bfc22b7d 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.copy.pass.cpp
@@ -15,7 +15,9 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
+#include <utility>
 
 #include "test_macros.h"
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
index a36e548c72d0d..098ffd1bd414c 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.default.pass.cpp
@@ -14,6 +14,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 #include "test_macros.h"
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
index 7bc4ffae3c25c..660ffe331785b 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/ctor.extents.pass.cpp
@@ -15,6 +15,7 @@
 #include <array>
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 template <size_t PaddingValue, class Extents>
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
index b77dcf99c4794..339359ff268f9 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/properties.pass.cpp
@@ -25,7 +25,9 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
+#include <utility>
 
 #include "test_macros.h"
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
index 8306c7bfd7e7a..05cd2211d5918 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/required_span_size.pass.cpp
@@ -14,6 +14,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 #include "test_macros.h"
diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
index 82a9bb90e50f8..56608c7477573 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/static_requirements.pass.cpp
@@ -11,6 +11,7 @@
 // <mdspan>
 
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 #include <type_traits>
 #include <utility>
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
index 8bdc53ee4e32b..7011547a91cc1 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.copy.pass.cpp
@@ -15,7 +15,9 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
+#include <utility>
 
 #include "test_macros.h"
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
index 73e6dc3288337..e34614a4805e8 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.default.pass.cpp
@@ -14,6 +14,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 #include "test_macros.h"
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
index 6526b54b963f9..98dd573d77ab3 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/ctor.extents.pass.cpp
@@ -15,6 +15,7 @@
 #include <array>
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 template <size_t PaddingValue, class Extents>
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
index 0adaab5c4d14c..d1ca3ed28a679 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/properties.pass.cpp
@@ -25,7 +25,9 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
+#include <utility>
 
 #include "test_macros.h"
 
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
index e4289707d5702..92f0658cc1125 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/required_span_size.pass.cpp
@@ -14,6 +14,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 
 #include "test_macros.h"
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
index 033ffce606911..27fd566b88829 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/static_requirements.pass.cpp
@@ -11,6 +11,7 @@
 // <mdspan>
 
 #include <cstddef>
+#include <cstdint>
 #include <mdspan>
 #include <type_traits>
 #include <utility>

>From 7b32242a766b75b5e7cf52266692f9c054dd3689 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Tue, 24 Mar 2026 12:07:16 +0800
Subject: [PATCH 6/6] add test

---
 .../mdspan/layout_left_padded/extents.verify.cpp     | 12 +++++++++---
 .../mdspan/layout_right_padded/extents.verify.cpp    | 12 +++++++++---
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp b/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
index 03e86d61050f9..f061d9a93bb3f 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_left_padded/extents.verify.cpp
@@ -13,6 +13,7 @@
 // template<class Extents>
 // class layout_left_padded::mapping;
 
+#include <cstdint>
 #include <mdspan>
 
 void not_extents() {
@@ -22,15 +23,20 @@ void not_extents() {
 
 void index_space_representable() {
   // expected-error@*:* {{layout_left_padded::mapping index space for static extents must be representable as index_type.}}
-  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<signed char, 20, 20>> mapping;
+  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<int8_t, 20, 20>> mapping;
+}
+
+void padding_value_representable() {
+  // expected-error@*:* {{layout_left_padded::mapping padding_value must be representable as index_type.}}
+  [[maybe_unused]] std::layout_left_padded<128>::mapping<std::extents<int8_t, 1>> mapping;
 }
 
 void padding_stride_representable() {
   // expected-error@*:* {{layout_left_padded::mapping padded stride for the first static extent must be representable as size_t and index_type.}}
-  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<signed char, 127, 1>> mapping;
+  [[maybe_unused]] std::layout_left_padded<4>::mapping<std::extents<int8_t, 127, 1>> mapping;
 }
 
 void padded_product_representable() {
   // expected-error@*:* {{layout_left_padded::mapping required span size for static extents must be representable as size_t and index_type.}}
-  [[maybe_unused]] std::layout_left_padded<64>::mapping<std::extents<signed char, 63, 2>> mapping;
+  [[maybe_unused]] std::layout_left_padded<64>::mapping<std::extents<int8_t, 63, 2>> mapping;
 }
diff --git a/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp b/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
index 370d8e1b453e4..238d9ba66dff1 100644
--- a/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/layout_right_padded/extents.verify.cpp
@@ -13,6 +13,7 @@
 // template<class Extents>
 // class layout_right_padded::mapping;
 
+#include <cstdint>
 #include <mdspan>
 
 void not_extents() {
@@ -22,15 +23,20 @@ void not_extents() {
 
 void index_space_representable() {
   // expected-error@*:* {{layout_right_padded::mapping index space for static extents must be representable as index_type.}}
-  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<signed char, 20, 20>> mapping;
+  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<int8_t, 20, 20>> mapping;
+}
+
+void padding_value_representable() {
+  // expected-error@*:* {{layout_right_padded::mapping padding_value must be representable as index_type.}}
+  [[maybe_unused]] std::layout_right_padded<128>::mapping<std::extents<int8_t, 1>> mapping;
 }
 
 void padding_stride_representable() {
   // expected-error@*:* {{layout_right_padded::mapping padded stride for the last static extent must be representable as size_t and index_type.}}
-  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<signed char, 0, 127>> mapping;
+  [[maybe_unused]] std::layout_right_padded<4>::mapping<std::extents<int8_t, 0, 127>> mapping;
 }
 
 void padded_product_representable() {
   // expected-error@*:* {{layout_right_padded::mapping required span size for static extents must be representable as size_t and index_type.}}
-  [[maybe_unused]] std::layout_right_padded<64>::mapping<std::extents<signed char, 2, 63>> mapping;
+  [[maybe_unused]] std::layout_right_padded<64>::mapping<std::extents<int8_t, 2, 63>> mapping;
 }



More information about the libcxx-commits mailing list