On Mon, 30 Jun 2025 at 11:48, Tomasz Kaminski <[email protected]> wrote:
>
>
>
> On Mon, Jun 30, 2025 at 9:58 AM Tomasz Kaminski <[email protected]> wrote:
>>
>>
>>
>> On Mon, Jun 30, 2025 at 9:25 AM Luc Grosheintz <[email protected]>
>> 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 <[email protected]>
>>> ---
>>>
>>> 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.
OK for trunk, thank you both.
>>
>>
>>>
>>>
>>> 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
>>>