+ return std::assume_aligned<byte_alignment>(__p)[__i];
+ }
+
+ constexpr typename offset_policy::data_handle_type
+ offset(data_handle_type __p, size_t __i) const noexcept
+ {
+ if !consteval
+ {
+ _GLIBCXX_DEBUG_ASSERT(
+ std::is_sufficiently_aligned<_ByteAlignment>(__p));
+ }
+ return std::assume_aligned<byte_alignment>(__p) + __i;
+ }
+ };
+#endif
+
namespace __mdspan
{
template<typename _Extents, typename _IndexType, size_t _Nm>
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/
std.cc.in
index 24411476ba0..40d2fa03c5a 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1858,10 +1858,13 @@ export namespace std
using std::layout_right;
using std::layout_stride;
using std::default_accessor;
+#if __glibcxx_aligned_accessor
+ using std::aligned_accessor;
+#endif
using std::mdspan;
- // FIXME layout_left_padded, layout_right_padded, aligned_accessor,
- // strided_slice, submdspan_mapping_result, full_extent_t, full_extent,
- // submdspan_extents, mdsubspan
+ // FIXME layout_left_padded, layout_right_padded, strided_slice,
+ // submdspan_mapping_result, full_extent_t, full_extent,
submdspan_extents,
+ // mdsubspan
}
#endif
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned.cc
new file mode 100644
index 00000000000..f84092f6d89
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned.cc
@@ -0,0 +1,43 @@
+// { dg-do compile { target c++26 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_from_other()
+{
+ std::aligned_accessor<double, 4*sizeof(double)> a4;
+ [[maybe_unused]] std::aligned_accessor<double, 2*sizeof(double)> a2(a4);
+ static_assert(std::is_nothrow_convertible_v<std::aligned_accessor<char,
4>,
+ std::aligned_accessor<char,
2>>);
+ static_assert(!std::is_constructible_v<std::aligned_accessor<char, 4>,
+ std::aligned_accessor<char, 2>>);
+ return true;
+}
+static_assert(test_from_other());
+
+constexpr bool
+test_from_default()
+{
+ std::default_accessor<double> ad;
+ [[maybe_unused]] std::aligned_accessor<double, 4*sizeof(double)> a4(ad);
+ static_assert(!std::is_convertible_v<std::default_accessor<char>,
+ std::aligned_accessor<char, 1>>);
+ static_assert(!std::is_convertible_v<std::default_accessor<char>,
+ std::aligned_accessor<char, 2>>);
+ static_assert(std::is_nothrow_constructible_v<
+ std::aligned_accessor<char, 4>, std::default_accessor<char>>);
+ return true;
+}
+static_assert(test_from_default());
+
+constexpr bool
+test_to_default()
+{
+ std::aligned_accessor<double, 4*sizeof(double)> a4;
+ [[maybe_unused]] std::default_accessor<double> ad = a4;
+ static_assert(std::is_nothrow_convertible_v<std::aligned_accessor<char,
2>,
+
std::default_accessor<char>>);
+ return true;
+}
+static_assert(test_to_default());
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned_neg.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned_neg.cc
new file mode 100644
index 00000000000..46d80bf4083
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/aligned_neg.cc
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++26 } }
+#include<mdspan>
+
+#include <cstdint>
+
+std::aligned_accessor<uint32_t, 0> a; // { dg-error "required
from here" }
+std::aligned_accessor<uint32_t, 7> b; // { dg-error "required
from here" }
+std::aligned_accessor<uint32_t, size_t(-1)> c; // { dg-error "required
from here" }
+
+std::aligned_accessor<uint32_t, 2> d; // { dg-error "required
from here" }
+
+std::aligned_accessor<int[2], 32> e; // { dg-error "required
from here" }
+
+class Abstract
+{
+ virtual void
+ foo() const = 0;
+};
+
+class Derived : public Abstract
+{
+ void
+ foo() const override
+ { }
+};
+
+std::aligned_accessor<Derived, alignof(int)> f_ok;
+std::aligned_accessor<Abstract, alignof(int)> f_err; // { dg-error
"required from here" }
+
+// { dg-prune-output "ByteAlignment must be a power of two" }
+// { dg-prune-output "ByteAlignment is too small for ElementType" }
+// { dg-prune-output "ElementType must not be an array type" }
+// { dg-prune-output "ElementType must not be an abstract" }
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_access_neg.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_access_neg.cc
new file mode 100644
index 00000000000..3511cef1c3a
--- /dev/null
+++
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_access_neg.cc
@@ -0,0 +1,23 @@
+// { dg-do run { target c++26 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <mdspan>
+#include <array>
+
+void
+test_unaligned_access()
+{
+ constexpr size_t N = 4;
+ alignas(N) std::array<char, 128> buffer{};
+ auto* unaligned = buffer.data() + 1;
+ auto a = std::aligned_accessor<char, N>{};
+
+ [[maybe_unused]] char x = a.access(unaligned, 0);
+}
+
+int
+main()
+{
+ test_unaligned_access();
+ return 0;
+};
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_offset_neg.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_offset_neg.cc
new file mode 100644
index 00000000000..319da5ffef3
--- /dev/null
+++
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/debug/aligned_offset_neg.cc
@@ -0,0 +1,23 @@
+// { dg-do run { target c++26 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <mdspan>
+#include <array>
+
+void
+test_unaligned_offset()
+{
+ constexpr size_t N = 4;
+ alignas(N) std::array<char, 128> buffer{};
+ auto* unaligned = buffer.data() + 1;
+ auto a = std::aligned_accessor<char, N>{};
+
+ [[maybe_unused]] char* x = a.offset(unaligned, 0);
+}
+
+int
+main()
+{
+ test_unaligned_offset();
+ return 0;
+};
diff --git
a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
index c3350353aae..d420fe885aa 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
@@ -82,10 +82,28 @@ template<template<typename T> typename Accessor>
static_assert(test_properties<std::default_accessor>());
+#ifdef __glibcxx_aligned_accessor
+template<size_t Mult>
+struct OverAlignedAccessorTrait
+{
+ template<typename T>
+ using type = std::aligned_accessor<T, Mult*alignof(T)>;
+};
+
+static_assert(test_properties<OverAlignedAccessorTrait<1>::type>());
+static_assert(test_properties<OverAlignedAccessorTrait<2>::type>());
+#endif
+
template<typename A>
constexpr size_t
accessor_alignment = alignof(typename A::element_type);
+#ifdef __glibcxx_aligned_accessor
+template<typename T, size_t N>
+ constexpr size_t
+ accessor_alignment<std::aligned_accessor<T, N>> = N;
+#endif
+
template<typename Accessor>
constexpr void
test_access(Accessor accessor)
@@ -121,5 +139,10 @@ main()
{
test_all<std::default_accessor<double>>();
static_assert(test_all<std::default_accessor<double>>());
+
+#ifdef __glibcxx_aligned_accessor
+ test_all<typename OverAlignedAccessorTrait<4>::type<double>>();
+ static_assert(test_all<typename
OverAlignedAccessorTrait<4>::type<double>>());
+#endif
return 0;
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
index 752060262a0..18826005971 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc
@@ -10,3 +10,11 @@
#elif __cplusplus > 202302L && __cpp_lib_mdspan != 202406L
#error "Feature test macro __cpp_lib_mdspan has the wrong value for C++26"
#endif
+
+#if __cplusplus > 202302L
+#ifndef __cpp_lib_aligned_accessor
+#error "Feature test macro __cpp_lib_aligned_accessor is missing for
<mdspan>"
+#elif __cpp_lib_aligned_accessor != 202411L
+#error "Feature test macro __cpp_lib_aligned_accessor has the wrong value"
+#endif
+#endif
--
2.50.0