On Tue, Jul 22, 2025 at 11:58 AM Tomasz Kaminski <tkami...@redhat.com> wrote:
> > > On Mon, Jul 21, 2025 at 10:19 AM Luc Grosheintz <luc.groshei...@gmail.com> > wrote: > >> All test code of default_accessor can be reused. This commit moves >> the reuseable code into a file generic.cc and prepares the tests for >> reuse with aligned_accessor. >> >> The AllocatorTrait creates a unified interface for creating both >> default_accessor<T> and aligned_accessor<T, N> typenames. >> >> libstdc++-v3/ChangeLog: >> >> * testsuite/23_containers/mdspan/accessors/default.cc: Delete. >> * testsuite/23_containers/mdspan/accessors/generic.cc: Slightly >> generalize the test code previously in default.cc. >> >> Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> >> --- >> .../23_containers/mdspan/accessors/default.cc | 99 ------------ >> .../23_containers/mdspan/accessors/generic.cc | 141 ++++++++++++++++++ >> 2 files changed, 141 insertions(+), 99 deletions(-) >> delete mode 100644 >> libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> create mode 100644 >> libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc >> >> diff --git >> a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> deleted file mode 100644 >> index c036f8ad10f..00000000000 >> --- a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/default.cc >> +++ /dev/null >> @@ -1,99 +0,0 @@ >> -// { 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/generic.cc >> b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc >> new file mode 100644 >> index 00000000000..600d152b690 >> --- /dev/null >> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc >> @@ -0,0 +1,141 @@ >> +// { dg-do run { target c++23 } } >> +#include <mdspan> >> + >> +#include <testsuite_hooks.h> >> + >> +template<typename Accessor> >> + constexpr bool >> + test_class_properties() >> + { >> + static_assert(std::is_trivially_copyable_v<Accessor>); >> + static_assert(std::semiregular<Accessor>); >> + return true; >> + } >> + >> +template<typename Accessor> >> + constexpr bool >> + 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>); >> + return true; >> + } >> + >> +class Base >> +{ }; >> + >> +class Derived : public Base >> +{ }; >> + >> +template<typename AccessorTrait> >> > I would make this a template template parameter in form: > template<template<typename> typename Accessor> > This way you could pass default_accessor directly, and for aligned accessor > pass an alias template. > Given next commit, we could make a test_properities() with accessor parameter, that will call test_class_properties, test_accessor_policy and test_ctor. > + constexpr bool >> + test_ctor() >> + { >> + // T -> T >> + static_assert(std::is_nothrow_constructible_v< >> + typename AccessorTrait::type<double>, >> + typename AccessorTrait::type<double>>); >> + static_assert(std::is_convertible_v< >> + typename AccessorTrait::type<double>, >> + typename AccessorTrait::type<double>>); >> + >> + // T -> const T >> + static_assert(std::is_convertible_v< >> + typename AccessorTrait::type<double>, >> + typename AccessorTrait::type<const double>>); >> + static_assert(std::is_convertible_v< >> + typename AccessorTrait::type<Derived>, >> + typename AccessorTrait::type<const Derived>>); >> + >> + // const T -> T >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<double>, >> + typename AccessorTrait::type<const double>>); >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<Derived>, >> + typename AccessorTrait::type<const Derived>>); >> + >> + // T <-> volatile T >> + static_assert(std::is_convertible_v< >> + typename AccessorTrait::type<int>, >> + typename AccessorTrait::type<volatile int>>); >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<int>, >> + typename AccessorTrait::type<volatile int>>); >> + >> + // size difference >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<char>, >> + typename AccessorTrait::type<int>>); >> + >> + // signedness >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<int>, >> + typename AccessorTrait::type<unsigned int>>); >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<unsigned int>, >> + typename AccessorTrait::type<int>>); >> + >> + // Derived <-> Base >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<Base>, >> + typename AccessorTrait::type<Derived>>); >> + static_assert(!std::is_constructible_v< >> + typename AccessorTrait::type<Derived>, >> + typename AccessorTrait::type<Base>>); >> + return true; >> + } >> + >> +struct DefaultAccessorTrait >> +{ >> + template<typename T> >> + using type = std::default_accessor<T>; >> +}; >> + >> +static_assert(test_class_properties<std::default_accessor<double>>()); >> +static_assert(test_accessor_policy<std::default_accessor<double>>()); >> +static_assert(test_ctor<DefaultAccessorTrait>()); >> + >> +template<typename A> >> + constexpr size_t >> + accessor_alignment = sizeof(typename A::element_type); >> + >> +template<typename Accessor> >> + constexpr void >> + test_access(Accessor accessor) >> + { >> + constexpr size_t N = accessor_alignment<Accessor>; >> + alignas(N) std::array<double, 5> a{10, 11, 12, 13, 14}; >> + VERIFY(accessor.access(a.data(), 0) == 10); >> + VERIFY(accessor.access(a.data(), 4) == 14); >> + } >> + >> +template<typename Accessor> >> + constexpr void >> + test_offset(Accessor accessor) >> + { >> + constexpr size_t N = accessor_alignment<Accessor>; >> + alignas(N) 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); >> + } >> + >> +template<typename Accessor> >> + constexpr bool >> + test_all() >> + { >> + auto accessor = Accessor{}; >> + test_offset(accessor); >> + test_access(accessor); >> + return true; >> + } >> + >> +int >> +main() >> +{ >> + test_all<std::default_accessor<double>>(); >> + static_assert(test_all<std::default_accessor<double>>()); >> + return 0; >> +} >> -- >> 2.50.0 >> >>