[libcxx-commits] [libcxx] [libc++] Implement P2897R7 aligned_accessor: An mdspan accessor expressing pointer over-alignment (PR #122603)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jan 11 10:27:10 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Damien L-G (dalg24)

<details>
<summary>Changes</summary>

Closes #<!-- -->118372 

---

Patch is 40.05 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/122603.diff


21 Files Affected:

- (modified) libcxx/docs/FeatureTestMacroTable.rst (+4) 
- (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1) 
- (modified) libcxx/include/CMakeLists.txt (+2) 
- (added) libcxx/include/__mdspan/aligned_accessor.h (+86) 
- (modified) libcxx/include/__mdspan/mdspan.h (+5-4) 
- (added) libcxx/include/__memory/is_sufficiently_aligned.h (+34) 
- (modified) libcxx/include/mdspan (+37-1) 
- (modified) libcxx/include/memory (+4) 
- (modified) libcxx/include/module.modulemap (+2) 
- (modified) libcxx/modules/std/mdspan.inc (+5) 
- (modified) libcxx/modules/std/memory.inc (+3) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp (+61) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp (+29) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp (+81) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.pass.cpp (+104) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.default.pass.cpp (+56) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/element_type.verify.cpp (+32) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/offset.pass.cpp (+61) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/operator.conversion.to.default_accessor.pass.cpp (+80) 
- (added) libcxx/test/std/containers/views/mdspan/aligned_accessor/types.pass.cpp (+70) 
- (added) libcxx/test/std/utilities/memory/ptr.align/is_sufficiently_aligned.pass.cpp (+105) 


``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index cfb0e5cfb129ce..ae8cbe61fd7d17 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -406,6 +406,8 @@ Status
     ----------------------------------------------------------------------------
     ``__cpp_lib_associative_heterogeneous_insertion``          *unimplemented*
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_aligned_accessor``                             ``202411L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_atomic_min_max``                               *unimplemented*
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_bind_front``                                   ``202306L``
@@ -450,6 +452,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_inplace_vector``                               *unimplemented*
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_is_sufficiently_aligned``                      ``202411L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_is_virtual_base_of``                           ``202406L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_is_within_lifetime``                           *unimplemented*
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index aa896e85fcb1fe..ae1f887947fe06 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -81,7 +81,7 @@
 "`P3379R0 <https://wg21.link/P3379R0>`__","Constrain ``std::expected`` equality operators","2024-11 (Wrocław)","","",""
 "`P0472R2 <https://wg21.link/P0472R2>`__","Put ``std::monostate`` in ``<utility>``","2024-11 (Wrocław)","","",""
 "`P2862R1 <https://wg21.link/P2862R1>`__","``text_encoding::name()`` should never return null values","2024-11 (Wrocław)","","",""
-"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","","",""
+"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","|Complete|","20",""
 "`P3355R1 <https://wg21.link/P3355R1>`__","Fix ``submdspan`` for C++26","2024-11 (Wrocław)","","",""
 "`P3222R0 <https://wg21.link/P3222R0>`__","Fix C++26 by adding transposed special cases for P2642 layouts","2024-11 (Wrocław)","","",""
 "`P3050R2 <https://wg21.link/P3050R2>`__","Fix C++26 by optimizing ``linalg::conjugated`` for noncomplex value types","2024-11 (Wrocław)","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index f7721b1047b81e..ad7574b8993d08 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -529,6 +529,7 @@ set(files
   __math/traits.h
   __math/trigonometric_functions.h
   __mbstate_t.h
+  __mdspan/aligned_accessor.h
   __mdspan/default_accessor.h
   __mdspan/extents.h
   __mdspan/layout_left.h
@@ -553,6 +554,7 @@ set(files
   __memory/construct_at.h
   __memory/destruct_n.h
   __memory/inout_ptr.h
+  __memory/is_sufficiently_aligned.h
   __memory/noexcept_move_assign_container.h
   __memory/out_ptr.h
   __memory/pointer_traits.h
diff --git a/libcxx/include/__mdspan/aligned_accessor.h b/libcxx/include/__mdspan/aligned_accessor.h
new file mode 100644
index 00000000000000..441c144c11aebb
--- /dev/null
+++ b/libcxx/include/__mdspan/aligned_accessor.h
@@ -0,0 +1,86 @@
+// -*- 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_ALIGNED_ACCESSOR_H
+#define _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__memory/assume_aligned.h>
+#include <__type_traits/is_abstract.h>
+#include <__type_traits/is_array.h>
+#include <__type_traits/is_convertible.h>
+#include <__type_traits/remove_const.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
+
+template <class _ElementType, size_t _ByteAlignment>
+struct aligned_accessor {
+  static_assert(_ByteAlignment != 0 && (_ByteAlignment & (_ByteAlignment - 1)) == 0,
+                "aligned_accessor: byte alignment must be a power of two");
+  static_assert(_ByteAlignment >= alignof(_ElementType), "aligned_accessor: insufficient byte alignment");
+  static_assert(!is_array_v<_ElementType>, "aligned_accessor: template argument may not be an array type");
+  static_assert(!is_abstract_v<_ElementType>, "aligned_accessor: template argument may not be an abstract class");
+
+  using offset_policy    = default_accessor<_ElementType>;
+  using element_type     = _ElementType;
+  using reference        = _ElementType&;
+  using data_handle_type = _ElementType*;
+
+  static constexpr size_t byte_alignment = _ByteAlignment;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor() noexcept = default;
+
+  template <class _OtherElementType, size_t _OtherByteAlignment>
+    requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment)
+  _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {}
+
+  template <class _OtherElementType>
+    requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>)
+  _LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {}
+
+  template <class _OtherElementType>
+    requires(is_convertible_v<element_type (*)[], _OtherElementType (*)[]>)
+  _LIBCPP_HIDE_FROM_ABI constexpr operator default_accessor<_OtherElementType>() const noexcept {
+    return {};
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept {
+    return std::assume_aligned<byte_alignment>(__p)[__i];
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr typename offset_policy::data_handle_type
+  offset(data_handle_type __p, size_t __i) const noexcept {
+    return std::assume_aligned<byte_alignment>(__p) + __i;
+  }
+};
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H
diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h
index 3f9b35b185b167..ef8db9f1f9789a 100644
--- a/libcxx/include/__mdspan/mdspan.h
+++ b/libcxx/include/__mdspan/mdspan.h
@@ -20,6 +20,7 @@
 #include <__assert>
 #include <__config>
 #include <__fwd/mdspan.h>
+#include <__mdspan/aligned_accessor.h>
 #include <__mdspan/default_accessor.h>
 #include <__mdspan/extents.h>
 #include <__type_traits/extent.h>
@@ -266,13 +267,13 @@ class mdspan {
 #  if _LIBCPP_STD_VER >= 26
 template <class _ElementType, class... _OtherIndexTypes>
   requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
-explicit mdspan(_ElementType*,
-                _OtherIndexTypes...) -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
+explicit mdspan(_ElementType*, _OtherIndexTypes...)
+    -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
 #  else
 template <class _ElementType, class... _OtherIndexTypes>
   requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
-explicit mdspan(_ElementType*,
-                _OtherIndexTypes...) -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
+explicit mdspan(_ElementType*, _OtherIndexTypes...)
+    -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
 #  endif
 
 template <class _Pointer>
diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h
new file mode 100644
index 00000000000000..4280920cabb4bc
--- /dev/null
+++ b/libcxx/include/__memory/is_sufficiently_aligned.h
@@ -0,0 +1,34 @@
+// -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
+#define _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <cstdint>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <size_t _Alignment, class _Tp>
+_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
+  return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
+}
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan
index a67ed1834e3bde..61f1b210dd03af 100644
--- a/libcxx/include/mdspan
+++ b/libcxx/include/mdspan
@@ -33,10 +33,14 @@ namespace std {
   template<class ElementType>
     class default_accessor;
 
+  // [mdspan.accessor.aligned], class template aligned_accessor
+  template<class ElementType, size_t ByteAlignment>
+    class aligned_accessor; // since C++26
+
   // [mdspan.mdspan], class template mdspan
   template<class ElementType, class Extents, class LayoutPolicy = layout_right,
            class AccessorPolicy = default_accessor<ElementType>>
-    class mdspan; // not implemented yet
+    class mdspan;
 }
 
 // extents synopsis
@@ -269,6 +273,38 @@ namespace std {
   };
 }
 
+// aligned_accessor synopsis
+
+namespace std {
+  template<class ElementType, size_t ByteAlignment>
+  struct aligned_accessor {
+    using offset_policy = default_accessor<ElementType>;
+    using element_type = ElementType;
+    using reference = ElementType&;
+    using data_handle_type = ElementType*;
+
+    static constexpr size_t byte_alignment = ByteAlignment;
+
+    constexpr aligned_accessor() noexcept = default;
+
+    template<class OtherElementType, size_t OtherByteAlignment>
+      constexpr aligned_accessor(
+        aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
+
+    template<class OtherElementType>
+      explicit constexpr aligned_accessor(
+        default_accessor<OtherElementType>) noexcept;
+
+    template<class OtherElementType>
+    constexpr operator default_accessor<OtherElementType>() const noexcept;
+
+    constexpr reference access(data_handle_type p, size_t i) const noexcept;
+
+    constexpr typename offset_policy::data_handle_type
+      offset(data_handle_type p, size_t i) const noexcept;
+  };
+}
+
 // mdspan synopsis
 
 namespace std {
diff --git a/libcxx/include/memory b/libcxx/include/memory
index fc62606ea0fd33..a6400bd29f4437 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -912,6 +912,9 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
 template<size_t N, class T>
 [[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20
 
+template<size_t Alignment, class T>
+  bool is_sufficiently_aligned(T* ptr); // since C++26
+
 // [out.ptr.t], class template out_ptr_t
 template<class Smart, class Pointer, class... Args>
   class out_ptr_t;                                          // since c++23
@@ -945,6 +948,7 @@ template<class Pointer = void, class Smart, class... Args>
 #  include <__memory/allocator_traits.h>
 #  include <__memory/auto_ptr.h>
 #  include <__memory/inout_ptr.h>
+#  include <__memory/is_sufficiently_aligned.h>
 #  include <__memory/out_ptr.h>
 #  include <__memory/pointer_traits.h>
 #  include <__memory/raw_storage_iterator.h>
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 07ab5649ae45cb..c4beb2dfa4f383 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1504,6 +1504,7 @@ 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" }
@@ -1539,6 +1540,7 @@ module std [system] {
     module destruct_n                         { header "__memory/destruct_n.h" }
     module fwd                                { header "__fwd/memory.h" }
     module inout_ptr                          { header "__memory/inout_ptr.h" }
+    module is_sufficiently_aligned            { header "__memory/is_sufficiently_aligned.h" }
     module noexcept_move_assign_container     { header "__memory/noexcept_move_assign_container.h" }
     module out_ptr                            { header "__memory/out_ptr.h" }
     module pointer_traits                     { header "__memory/pointer_traits.h" }
diff --git a/libcxx/modules/std/mdspan.inc b/libcxx/modules/std/mdspan.inc
index 5e65993383cdc0..c8cc78badb7d59 100644
--- a/libcxx/modules/std/mdspan.inc
+++ b/libcxx/modules/std/mdspan.inc
@@ -28,6 +28,11 @@ export namespace std {
   // [mdspan.accessor.default], class template default_accessor
   using std::default_accessor;
 
+#  if _LIBCPP_STD_VER >= 26
+  // [mdspan.accessor.aligned], class template aligned_accessor
+  using std::aligned_accessor;
+#  endif // _LIBCPP_STD_VER >= 26
+
   // [mdspan.mdspan], class template mdspan
   using std::mdspan;
 #endif // _LIBCPP_STD_VER >= 23
diff --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc
index 82056e426d06c9..c25e9e3443e9cf 100644
--- a/libcxx/modules/std/memory.inc
+++ b/libcxx/modules/std/memory.inc
@@ -17,6 +17,9 @@ export namespace std {
   // [ptr.align], pointer alignment
   using std::align;
   using std::assume_aligned;
+#if _LIBCPP_STD_VER >= 26
+  using std::is_sufficiently_aligned;
+#endif
 
   // [obj.lifetime], explicit lifetime management
   //  using std::start_lifetime_as;
diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp
new file mode 100644
index 00000000000000..145dc79eda73d4
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <mdspan>
+
+// constexpr reference access(data_handle_type p, size_t i) const noexcept;
+//
+// Effects: Equivalent to: return assume_aligned<byte_alignment>(p)[i];
+
+#include <mdspan>
+#include <cassert>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+template <class T, size_t N>
+constexpr void test_access() {
+  ElementPool<std::remove_const_t<T>, 10 + N> data;
+  T* ptr = data.get_ptr();
+  std::aligned_accessor<T, N> acc;
+  for (size_t i = 0; i < 10 + N; i++) {
+    if (reinterpret_cast<std::uintptr_t>(ptr + i) % N == 0) {
+      std::same_as<typename std::aligned_accessor<T, N>::reference> decltype(auto) x = acc.access(ptr, i);
+      ASSERT_NOEXCEPT(acc.access(ptr, i));
+      assert(&x == ptr + i);
+    }
+  }
+}
+
+template <class T>
+constexpr void test_it() {
+  constexpr size_t N = alignof(T);
+  test_access<T, N>();
+  test_access<T, 2 * N>();
+  test_access<T, 4 * N>();
+  test_access<T, 8 * N>();
+  test_access<T, 16 * N>();
+}
+
+constexpr bool test() {
+  test_it<int>();
+  test_it<const int>();
+  test_it<MinimalElementType>();
+  test_it<const MinimalElementType>();
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  //static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp
new file mode 100644
index 00000000000000..fbc8386a72dede
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp
@@ -0,0 +1,29 @@
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <mdspan>
+
+// template<class ElementType, size_t ByteAlignment>
+// class aligned_accessor;
+
+// ByteAlignement is required to be a power of two and greater or equal to alignof(ElementType).
+
+#include <mdspan>
+
+void not_power_of_two() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: byte alignment must be a power of two}}
+  [[maybe_unused]] std::aligned_accessor<int, 12> acc;
+}
+
+struct alignas(8) S {};
+
+void insufficiently_aligned() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: insufficient byte alignment}}
+  [[maybe_unused]] std::aligned_accessor<S, 4> acc;
+}
diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp
new file mode 100644
index 00000000000000..339c12bb7c6c54
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <mdspan>
+//
+// template<class OtherElementType>
+//   explicit constexpr aligned_accessor(
+//     default_accessor<OtherElementType>) noexcept {}
+//
+// Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
+
+#include <mdspan>
+#include <cassert>
+#include <cstdint>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+struct Base {};
+struct Derived : public Base {};
+
+template <class FromT, class ToT, size_t ToN>
+constexpr void test_conversion() {
+  std::default_accessor<FromT> from;
+  ASSERT_NOEXCEPT(std::aligned_accessor<ToT, ToN>(from));
+  [[maybe_unused]] std::aligned_accessor<ToT, ToN> to(from);
+  // check that the constructor is explicit
+  static_assert(std::is_nothrow_constructible_v<std::aligned_accessor<ToT, ToN>, std::default_accessor<ToT>>);
+  static_assert(!std::is_convertible_v<std::default_accessor<ToT>, std::aligned_accessor<ToT, ToN>>);
+}
+
+template <class From, class To>
+constexpr void test_it() {
+  constexpr size_t N = alignof(To);
+  test_conversion<From, To, N>();
+  test_conversion<From, To, 2 * N>();
+  test_conversion<From, To, 4 * N>();
+  test_conversion<From, To, 8 * N>();
+  test_conversion<From, To, 16 * N>();
+  test_conversion<From, To, 32 * N>(...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/122603


More information about the libcxx-commits mailing list