On Mon, Jun 30, 2025 at 9:58 AM Tomasz Kaminski <tkami...@redhat.com> wrote:
> > > On Mon, Jun 30, 2025 at 9:25 AM Luc Grosheintz <luc.groshei...@gmail.com> > wrote: > >> libstdc++-v3/ChangeLog: >> >> * include/std/mdspan (default_accessor): New class. >> * src/c++23/std.cc.in: Register default_accessor. >> * testsuite/23_containers/mdspan/accessors/default.cc: New test. >> * testsuite/23_containers/mdspan/accessors/default_neg.cc: New >> test. >> >> Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> >> --- >> >> Version of v5 with all local changes included. >> > LGTM, tested locally and now running a full test suite. > Once it will get approval from Jonathan, I will handle merging it. > All test passed. > > >> >> libstdc++-v3/include/std/mdspan | 31 ++++++ >> libstdc++-v3/src/c++23/std.cc.in | 3 +- >> .../23_containers/mdspan/accessors/default.cc | 99 +++++++++++++++++++ >> .../mdspan/accessors/default_neg.cc | 23 +++++ >> 4 files changed, 155 insertions(+), 1 deletion(-) >> create mode 100644 >> libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> create mode 100644 >> libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc >> >> diff --git a/libstdc++-v3/include/std/mdspan >> b/libstdc++-v3/include/std/mdspan >> index 6dc2441f80b..c72a64094b7 100644 >> --- a/libstdc++-v3/include/std/mdspan >> +++ b/libstdc++-v3/include/std/mdspan >> @@ -1004,6 +1004,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> [[no_unique_address]] _S_strides_t _M_strides; >> }; >> >> + template<typename _ElementType> >> + struct default_accessor >> + { >> + static_assert(!is_array_v<_ElementType>, >> + "ElementType must not be an array type"); >> + static_assert(!is_abstract_v<_ElementType>, >> + "ElementType must not be an abstract class type"); >> + >> + using offset_policy = default_accessor; >> + using element_type = _ElementType; >> + using reference = element_type&; >> + using data_handle_type = element_type*; >> + >> + constexpr >> + default_accessor() noexcept = default; >> + >> + template<typename _OElementType> >> + requires is_convertible_v<_OElementType(*)[], element_type(*)[]> >> + constexpr >> + default_accessor(default_accessor<_OElementType>) noexcept >> + { } >> + >> + constexpr reference >> + access(data_handle_type __p, size_t __i) const noexcept >> + { return __p[__i]; } >> + >> + constexpr data_handle_type >> + offset(data_handle_type __p, size_t __i) const noexcept >> + { return __p + __i; } >> + }; >> + >> _GLIBCXX_END_NAMESPACE_VERSION >> } >> #endif >> diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/ >> std.cc.in >> index 9336118f5d9..e692caaa5f9 100644 >> --- a/libstdc++-v3/src/c++23/std.cc.in >> +++ b/libstdc++-v3/src/c++23/std.cc.in >> @@ -1850,7 +1850,8 @@ export namespace std >> using std::layout_left; >> using std::layout_right; >> using std::layout_stride; >> - // FIXME layout_left_padded, layout_right_padded, default_accessor and >> mdspan >> + using std::default_accessor; >> + // FIXME layout_left_padded, layout_right_padded, aligned_accessor and >> mdspan >> } >> #endif >> >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> new file mode 100644 >> index 00000000000..c036f8ad10f >> --- /dev/null >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> @@ -0,0 +1,99 @@ >> +// { dg-do run { target c++23 } } >> +#include <mdspan> >> + >> +#include <testsuite_hooks.h> >> + >> +constexpr size_t dyn = std::dynamic_extent; >> + >> +template<typename Accessor> >> + constexpr void >> + test_accessor_policy() >> + { >> + static_assert(std::copyable<Accessor>); >> + static_assert(std::is_nothrow_move_constructible_v<Accessor>); >> + static_assert(std::is_nothrow_move_assignable_v<Accessor>); >> + static_assert(std::is_nothrow_swappable_v<Accessor>); >> + } >> + >> +constexpr bool >> +test_access() >> +{ >> + std::default_accessor<double> accessor; >> + std::array<double, 5> a{10, 11, 12, 13, 14}; >> + VERIFY(accessor.access(a.data(), 0) == 10); >> + VERIFY(accessor.access(a.data(), 4) == 14); >> + return true; >> +} >> + >> +constexpr bool >> +test_offset() >> +{ >> + std::default_accessor<double> accessor; >> + std::array<double, 5> a{10, 11, 12, 13, 14}; >> + VERIFY(accessor.offset(a.data(), 0) == a.data()); >> + VERIFY(accessor.offset(a.data(), 4) == a.data() + 4); >> + return true; >> +} >> + >> +class Base >> +{ }; >> + >> +class Derived : public Base >> +{ }; >> + >> +constexpr void >> +test_ctor() >> +{ >> + // T -> T >> + >> static_assert(std::is_nothrow_constructible_v<std::default_accessor<double>, >> + >> std::default_accessor<double>>); >> + static_assert(std::is_convertible_v<std::default_accessor<double>, >> + std::default_accessor<double>>); >> + >> + // T -> const T >> + static_assert(std::is_convertible_v<std::default_accessor<double>, >> + std::default_accessor<const >> double>>); >> + static_assert(std::is_convertible_v<std::default_accessor<Derived>, >> + std::default_accessor<const >> Derived>>); >> + >> + // const T -> T >> + static_assert(!std::is_constructible_v<std::default_accessor<double>, >> + std::default_accessor<const >> double>>); >> + static_assert(!std::is_constructible_v<std::default_accessor<Derived>, >> + std::default_accessor<const >> Derived>>); >> + >> + // T <-> volatile T >> + static_assert(std::is_convertible_v<std::default_accessor<int>, >> + std::default_accessor<volatile >> int>>); >> + static_assert(!std::is_constructible_v<std::default_accessor<int>, >> + std::default_accessor<volatile >> int>>); >> + >> + // size difference >> + static_assert(!std::is_constructible_v<std::default_accessor<char>, >> + std::default_accessor<int>>); >> + >> + // signedness >> + static_assert(!std::is_constructible_v<std::default_accessor<int>, >> + std::default_accessor<unsigned >> int>>); >> + static_assert(!std::is_constructible_v<std::default_accessor<unsigned >> int>, >> + std::default_accessor<int>>); >> + >> + // Derived <-> Base >> + static_assert(!std::is_constructible_v<std::default_accessor<Base>, >> + std::default_accessor<Derived>>); >> + static_assert(!std::is_constructible_v<std::default_accessor<Derived>, >> + std::default_accessor<Base>>); >> + >> +} >> + >> +int >> +main() >> +{ >> + test_accessor_policy<std::default_accessor<double>>(); >> + test_access(); >> + static_assert(test_access()); >> + test_offset(); >> + static_assert(test_offset()); >> + test_ctor(); >> + return 0; >> +} >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc >> new file mode 100644 >> index 00000000000..f8da2b569ca >> --- /dev/null >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default_neg.cc >> @@ -0,0 +1,23 @@ >> +// { dg-do compile { target c++23 } } >> +#include<mdspan> >> + >> +std::default_accessor<int[3]> a; // { dg-error "required from here" } >> + >> +class AbstractBase >> +{ >> + virtual void >> + foo() const = 0; >> +}; >> + >> +class Derived : public AbstractBase >> +{ >> + void >> + foo() const override >> + { } >> +}; >> + >> +std::default_accessor<Derived> b_ok; >> +std::default_accessor<AbstractBase> b_err; // { dg-error "required from >> here"} >> + >> +// { dg-prune-output "ElementType must not be an array type" } >> +// { dg-prune-output "ElementType must not be an abstract" } >> -- >> 2.49.0 >> >>