On Sun, May 18, 2025 at 10:14 PM Luc Grosheintz <luc.groshei...@gmail.com> wrote:
> Implements a suite of tests for the currently implemented parts of > layout_left. The individual tests are templated over the layout type, to > allow reuse as more layouts are added. > > libstdc++-v3/ChangeLog: > > * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: New > test. > * testsuite/23_containers/mdspan/layouts/ctors.cc: New test. > * testsuite/23_containers/mdspan/layouts/mapping.cc: New test. > > Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> > --- > .../mdspan/layouts/class_mandate_neg.cc | 22 + > .../23_containers/mdspan/layouts/ctors.cc | 258 ++++++++++ > .../23_containers/mdspan/layouts/mapping.cc | 445 ++++++++++++++++++ > 3 files changed, 725 insertions(+) > create mode 100644 > libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > > diff --git > a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > new file mode 100644 > index 00000000000..f122541b3e8 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > @@ -0,0 +1,22 @@ > +// { dg-do compile { target c++23 } } > +#include<mdspan> > + > +#include <cstdint> > + > +constexpr size_t dyn = std::dynamic_extent; > +static constexpr size_t n = (size_t(1) << 7) - 1; > I would use numeric_limits_max<unit8_t> here. > + > +template<typename Layout> > + struct A > + { > + typename Layout::mapping<std::extents<uint8_t>> m0; > + typename Layout::mapping<std::extents<uint8_t, n, 2, dyn>> m1; > + typename Layout::mapping<std::extents<uint8_t, n, 2, 0>> m2; > + > + using extents_type = std::extents<uint8_t, n, 4>; > + typename Layout::mapping<extents_type> m3; // { dg-error "required > from" } > + }; > + > +A<std::layout_left> a_left; // { dg-error "required > from" } > + > +// { dg-prune-output "must be representable as index_type" } > diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > new file mode 100644 > index 00000000000..4592a05dec8 > --- /dev/null > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > @@ -0,0 +1,258 @@ > +// { dg-do run { target c++23 } } > +#include <mdspan> > + > +#include <testsuite_hooks.h> > + > +constexpr size_t dyn = std::dynamic_extent; > + > +template<typename Mapping, typename OExtents> > + constexpr void > + verify_from_exts(OExtents exts) > + { > + auto m = Mapping(exts); > + VERIFY(m.extents() == exts); > + } > + > + > +template<typename SMapping, typename OMapping> > + constexpr void > + verify_from_mapping(OMapping other) > + { > + auto m = SMapping(other); > + VERIFY(m.extents() == other.extents()); > + } > + > +template<typename Mapping, typename OExtents> > + requires (std::__mdspan::__is_extents<OExtents>) > + constexpr void > + verify(OExtents oexts) > + { In general, wen possible we prefer to not use internal details in tests. I would use if constexpr with requires { typename Other::layout_type; }, ie. template<typename Mapping, typename Source> cosntexpr void verify(Source const& src) { if constexpr (requires { typename Other::layout_type; }) verify_from_mapping(src) else verify_from_extents(src); } + auto m = Mapping(oexts); > + VERIFY(m.extents() == oexts); > + } > + > +template<typename Mapping, typename OMapping> > + requires (std::__mdspan::__standardized_mapping<OMapping>) > + constexpr void > + verify(OMapping other) > + { > + constexpr auto rank = Mapping::extents_type::rank(); > + auto m = Mapping(other); > + VERIFY(m.extents() == other.extents()); > + if constexpr (rank > 0) > + for(size_t i = 0; i < rank; ++i) > + VERIFY(std::cmp_equal(m.stride(i), other.stride(i))); > Why is this not checked in verify_from_mapping? > + } > + > + > +template<typename To, typename From> > + constexpr void > + verify_nothrow_convertible(From from) > + { > + static_assert(std::is_nothrow_constructible_v<To, From>); > I would call `verify_convertible` here, instead of these two lines. > + static_assert(std::is_convertible_v<From, To>); > + verify<To>(from); > + } > + > +template<typename To, typename From> > + constexpr void > + verify_convertible(From from) > + { > + static_assert(std::is_convertible_v<From, To>); > + verify<To>(from); > + } > + > +template<typename To, typename From> > + constexpr void > + verify_constructible(From from) > + { > + static_assert(!std::is_convertible_v<From, To>); > + static_assert(!std::is_nothrow_constructible_v<To, From>); > Implementations are allowed to add noexcept on the functions, so I would not perform this checks. See: https://eel.is/c++draft/res.on.exception.handling#5 > + static_assert(std::is_constructible_v<To, From>); > + verify<To>(from); > + } > + > +template<typename To, typename From> > + constexpr void > + verify_nothrow_constructible(From from) > + { > + static_assert(!std::is_convertible_v<From, To>); > + static_assert(std::is_nothrow_constructible_v<To, From>); > With the change above, I would call verify verify_constructible. > + verify<To>(from); > + } > + > +template<typename Mapping, typename OExtents> > + constexpr void > + assert_not_constructible() > + { > + static_assert(!std::is_constructible_v<Mapping, OExtents>); > + } > + > +// ctor: mapping(const extents&) > +namespace from_extents > +{ > + template<typename Layout, typename Extents, typename OExtents> > + constexpr void > + verify_nothrow_convertible(OExtents oexts) > + { > + using Mapping = typename Layout::mapping<Extents>; > + ::verify_nothrow_convertible<Mapping>(oexts); > + } > + > + template<typename Layout, typename Extents, typename OExtents> > + constexpr void > + verify_nothrow_constructible(OExtents oexts) > + { > + using Mapping = typename Layout::mapping<Extents>; > + ::verify_nothrow_constructible<Mapping>(oexts); > + } > + > + template<typename Layout, typename Extents, typename OExtents> > + constexpr void > + assert_not_constructible() > + { > + using Mapping = typename Layout::mapping<Extents>; > + ::assert_not_constructible<Mapping, OExtents>(); > + } > + > + template<typename Layout> > + constexpr bool > + test_ctor() > + { > + verify_nothrow_convertible<Layout, std::extents<int>>( > + std::extents<int>{}); > + > + verify_nothrow_convertible<Layout, std::extents<int, 2>>( > + std::extents<int, 2>{}); > + > + verify_nothrow_convertible<Layout, std::extents<int, dyn, 3>>( > + std::extents<int, dyn, 3>{2}); > + > + verify_nothrow_constructible<Layout, std::extents<unsigned int>>( > + std::extents<int>{}); > + > + verify_nothrow_constructible<Layout, std::extents<int, dyn>>( > + std::extents<int, 2>{}); > + > + verify_nothrow_constructible<Layout, std::extents<int, dyn, 3>>( > + std::extents<int, 2, 3>{}); > + > + assert_not_constructible<Layout, std::extents<int>, > + std::extents<unsigned int>>(); > + assert_not_constructible<Layout, std::extents<int, 2>, > + std::extents<int, dyn>>(); > + assert_not_constructible<Layout, std::extents<int, 2, 3>, > + std::extents<int, dyn, 3>>(); > + return true; > + } > + > + template<typename Layout, typename Extents> > + constexpr void > + assert_deducible(Extents exts) > + { > + typename Layout::mapping m(exts); > + static_assert(std::same_as<decltype(m), > + typename Layout::mapping<Extents>>); > + } > + > + template<typename Layout> > + constexpr void > + test_deducible() > + { > + assert_deducible<Layout>(std::extents<int>()); > + assert_deducible<Layout>(std::extents<int, 1>()); > + assert_deducible<Layout>(std::extents<int, 1, 2, dyn>(3)); > + } > + > + template<typename Layout> > + constexpr void > + test_all() > + { > + test_ctor<Layout>(); > + static_assert(test_ctor<Layout>()); > + test_deducible<Layout>(); > + } > +} > + > +// ctor: mapping(mapping<OExtents>) > +namespace from_same_layout > +{ > + template<typename Layout, typename Extents, typename OExtents> > + constexpr void > + verify_nothrow_convertible(OExtents exts) > + { > + using Mapping = typename Layout::mapping<Extents>; > + using OMapping = typename Layout::mapping<OExtents>; > + > + ::verify_nothrow_convertible<Mapping>(OMapping(exts)); > + } > + > + template<typename Layout, typename Extents, typename OExtents> > + constexpr void > + verify_nothrow_constructible(OExtents exts) > + { > + using Mapping = typename Layout::mapping<Extents>; > + using OMapping = typename Layout::mapping<OExtents>; > + > + ::verify_nothrow_constructible<Mapping>(OMapping(exts)); > + } > + > + template<typename Layout> > + constexpr bool > + test_ctor() > + { > + verify_nothrow_convertible<Layout, std::extents<unsigned int>>( > + std::extents<int>{}); > + > + verify_nothrow_constructible<Layout, std::extents<int>>( > + std::extents<unsigned int>{}); > + > + assert_not_constructible< > + typename Layout::mapping<std::extents<int>>, > + typename Layout::mapping<std::extents<int, 1>>>(); > + > + assert_not_constructible< > + typename Layout::mapping<std::extents<int, 1>>, > + typename Layout::mapping<std::extents<int>>>(); > + > + verify_nothrow_constructible<Layout, std::extents<int, 1>>( > + std::extents<int, dyn>{1}); > + > + verify_nothrow_convertible<Layout, std::extents<int, dyn>>( > + std::extents<int, 1>{}); > + > + assert_not_constructible< > + typename Layout::mapping<std::extents<int, 1, 2>>, > + typename Layout::mapping<std::extents<int, 1>>>(); > + > + verify_nothrow_constructible<Layout, std::extents<int, 1, 2>>( > + std::extents<int, dyn, 2>{1}); > + > + verify_nothrow_convertible<Layout, std::extents<int, dyn, 2>>( > + std::extents<int, 1, 2>{}); > + return true; > + } > + > + template<typename Layout> > + constexpr void > + test_all() > + { > + test_ctor<Layout>(); > + static_assert(test_ctor<Layout>()); > + } > +} > + > +template<typename Layout> > + constexpr void > + test_all() > + { > + from_extents::test_all<Layout>(); > + from_same_layout::test_all<Layout>(); > + } > + > +int > +main() > +{ > + test_all<std::layout_left>(); > + return 0; > +} > diff --git > a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > new file mode 100644 > index 00000000000..18f3548df67 > --- /dev/null > +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > @@ -0,0 +1,445 @@ > +// { dg-do run { target c++23 } } > +#include <mdspan> > + > +#include <cstdint> > +#include <testsuite_hooks.h> > + > +constexpr size_t dyn = std::dynamic_extent; > + > +template<typename Layout, typename Extents> > + constexpr bool > + test_mapping_properties() > + { > + using M = typename Layout::mapping<Extents>; > + static_assert(std::__mdspan::__is_extents<typename M::extents_type>); > + static_assert(std::copyable<M>); > + static_assert(std::is_nothrow_move_constructible_v<M>); > + static_assert(std::is_nothrow_move_assignable_v<M>); > + static_assert(std::is_nothrow_swappable_v<M>); > + static_assert(std::is_same_v<typename M::extents_type, Extents>); > + static_assert(std::is_same_v<typename M::index_type, > + typename M::extents_type::index_type>); > + static_assert(std::is_same_v<typename M::size_type, > + typename M::extents_type::size_type>); > + static_assert(std::is_same_v<typename M::rank_type, > + typename M::extents_type::rank_type>); > + static_assert(std::is_same_v<typename M::layout_type, Layout>); > + > + static_assert(std::is_trivially_copyable_v<M>); > + static_assert(std::regular<M>); > + > + static_assert(M::is_always_unique() && M::is_unique()); > + static_assert(M::is_always_strided() && M::is_strided()); > + return true; > + } > + > +template<typename Layout> > + constexpr bool > + test_mapping_properties_all() > + { > + test_mapping_properties<Layout, std::extents<int>>(); > + test_mapping_properties<Layout, std::extents<int, 1>>(); > + test_mapping_properties<Layout, std::extents<int, dyn>>(); > + test_mapping_properties<Layout, std::extents<int, dyn, dyn>>(); > + return true; > + } > + > +// Check operator()(Indices...) > +template<typename Mapping, size_t N> > + constexpr typename Mapping::index_type > + linear_index(const Mapping& mapping, > + const std::array<typename Mapping::index_type, N>& indices) > + { > + typename Mapping::index_type ret = 0; > + for(size_t r = 0; r < indices.size(); ++r) > + ret += indices[r] * mapping.stride(r); > + return ret; > + } > + > +template<typename Mapping, typename... Indices> > + constexpr void > + test_linear_index(const Mapping& m, Indices... i) > + { > + using index_type = typename Mapping::index_type; > + index_type expected = linear_index(m, std::array{index_type(i)...}); > + VERIFY(m(i...) == expected); > + VERIFY(m(uint8_t(i)...) == expected); > + } > + > +template<typename Layout> > + constexpr void > + test_linear_index_0d() > + { > + constexpr typename Layout::mapping<std::extents<int>> m; > + VERIFY(m() == 0); > + } > + > +template<typename Layout> > + constexpr void > + test_linear_index_1d() > + { > + typename Layout::mapping<std::extents<int, 5>> m; > + test_linear_index(m, 0); > + test_linear_index(m, 1); > + test_linear_index(m, 4); > + } > + > +template<typename Layout> > + constexpr void > + test_linear_index_2d() > + { > + typename Layout::mapping<std::extents<int, 3, 256>> m; > + test_linear_index(m, 0, 0); > + test_linear_index(m, 1, 0); > + test_linear_index(m, 0, 1); > + test_linear_index(m, 1, 1); > + test_linear_index(m, 2, 4); > + } > + > + > +template<typename Layout> > + struct MappingFactory > + { > + template<typename Extents> > + static constexpr typename Layout::mapping<Extents> > + create(Extents exts) > + { return exts; } > This call to this function be replaced with: typename Layout::mapping<Extents> m(std::extents(3, 5, 7)); I think expressing this directly would help. > + }; > + > +template<typename Layout> > + constexpr void > + test_linear_index_3d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3, 5, 7)); > + test_linear_index(m, 0, 0, 0); > + test_linear_index(m, 1, 0, 0); > + test_linear_index(m, 0, 1, 0); > + test_linear_index(m, 0, 0, 1); > + test_linear_index(m, 1, 1, 0); > + test_linear_index(m, 2, 4, 6); > + } > + > +struct IntLikeA > +{ > + operator int() > + { return 0; } > +}; > + > +struct IntLikeB > +{ > + operator int() noexcept > + { return 0; } > +}; > + > +struct NotIntLike > +{ }; > + > +template<typename Layout> > + constexpr void > + test_has_linear_index_0d() > + { > + using Mapping = typename Layout::mapping<std::extents<int>>; > + static_assert(std::invocable<Mapping>); > + static_assert(!std::invocable<Mapping, int>); > + static_assert(!std::invocable<Mapping, IntLikeA>); > + static_assert(!std::invocable<Mapping, IntLikeB>); > + static_assert(!std::invocable<Mapping, NotIntLike>); > + } > + > +template<typename Layout> > + constexpr void > + test_has_linear_index_1d() > + { > + using Mapping = typename Layout::mapping<std::extents<int, 3>>; > + static_assert(std::invocable<Mapping, int>); > + static_assert(!std::invocable<Mapping>); > + static_assert(!std::invocable<Mapping, IntLikeA>); > + static_assert(std::invocable<Mapping, IntLikeB>); > + static_assert(!std::invocable<Mapping, NotIntLike>); > + static_assert(std::invocable<Mapping, double>); > + } > + > +template<typename Layout> > + constexpr void > + test_has_linear_index_2d() > + { > + using Mapping = typename Layout::mapping<std::extents<int, 3, 5>>; > + static_assert(std::invocable<Mapping, int, int>); > + static_assert(!std::invocable<Mapping, int>); > + static_assert(!std::invocable<Mapping, IntLikeA, int>); > + static_assert(std::invocable<Mapping, IntLikeB, int>); > + static_assert(!std::invocable<Mapping, NotIntLike, int>); > + static_assert(std::invocable<Mapping, double, double>); > + } > + > +template<typename Layout> > + constexpr bool > + test_linear_index_all() > + { > + test_linear_index_0d<Layout>(); > + test_linear_index_1d<Layout>(); > + test_linear_index_2d<Layout>(); > + test_linear_index_3d<Layout>(); > + test_has_linear_index_0d<Layout>(); > + test_has_linear_index_1d<Layout>(); > + test_has_linear_index_2d<Layout>(); > + return true; > + } > + > +template<typename Mapping, typename Mapping::index_type... Counts> > + constexpr typename Mapping::index_type > + linear_index_end_impl(Mapping m, > + std::integer_sequence<typename Mapping::index_type, Counts...>) > I would define this as local lambda inside linear_index_end: auto __impl = [&m]<typename Mapping::index_type... Counts> { // code you have here. } return _impl(make_index_sequence(...); > + { > + if constexpr (sizeof...(Counts) == 0) > I do not think you need this special case, it fails from the specification below. as m((exts.extent(Counts) - 1)...) + 1 becomes m() + 1. > + return 1; > + else > + { > + auto exts = m.extents(); > + if(((exts.extent(Counts) == 0) || ...)) > + return 0; > + return m((exts.extent(Counts) - 1)...) + 1; > + } > + } > + > +template<typename Mapping> > + constexpr typename Mapping::index_type > + linear_index_end(Mapping m) > + { > + using index_type = typename Mapping::index_type; > + constexpr size_t rank = Mapping::extents_type::rank(); > + return linear_index_end_impl(m, > + std::make_integer_sequence<index_type, rank>()); > + } > + > +// Check required_span_size > +template<typename Mapping> > + constexpr void > + test_required_span_size(Mapping m) > + { VERIFY(m.required_span_size() == linear_index_end(m)); } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_0d() > + { > + typename Layout::mapping<std::extents<int>> m; > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_1d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3)); > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_2d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3, 5)); > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_3d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3, 5, 7)); > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_zero_1d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3, 0)); > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr void > + test_required_span_size_zero_3d() > + { > + auto m = MappingFactory<Layout>::create(std::extents(3, 0, 7)); > + test_required_span_size(m); > + } > + > +template<typename Layout> > + constexpr bool > + test_required_span_size_all() > + { > + test_required_span_size_0d<Layout>(); > + test_required_span_size_1d<Layout>(); > + test_required_span_size_2d<Layout>(); > + test_required_span_size_3d<Layout>(); > + test_required_span_size_zero_1d<Layout>(); > + test_required_span_size_zero_3d<Layout>(); > + return true; > + } > + > +// Check stride > +template<typename Layout> > + constexpr void > + test_stride_1d() > + { > + std::layout_left::mapping<std::extents<int, 3>> m; > + VERIFY(m.stride(0) == 1); > + } > + > +template<typename Layout> > + constexpr void > + test_stride_2d(); > + > +template<> > + constexpr void > + test_stride_2d<std::layout_left>() > + { > + std::layout_left::mapping<std::extents<int, 3, 5>> m; > + VERIFY(m.stride(0) == 1); > + VERIFY(m.stride(1) == 3); > + } > + > +template<typename Layout> > + constexpr void > + test_stride_3d(); > + > +template<> > + constexpr void > + test_stride_3d<std::layout_left>() > + { > + std::layout_left::mapping m(std::dextents<int, 3>(3, 5, 7)); > + VERIFY(m.stride(0) == 1); > + VERIFY(m.stride(1) == 3); > + VERIFY(m.stride(2) == 3*5); > + } > + > +template<typename Layout> > + constexpr bool > + test_stride_all() > + { > + test_stride_1d<Layout>(); > + test_stride_2d<Layout>(); > + test_stride_3d<Layout>(); > + return true; > + } > + > +template<typename Mapping> > + concept has_stride = requires (Mapping m) > + { > + { m.stride(0) } -> std::same_as<typename Mapping::index_type>; > + }; > + > +template<typename Layout> > + constexpr void > + test_has_stride_0d() > + { > + using Mapping = typename Layout::mapping<std::extents<int>>; > + constexpr bool expected = false; > + static_assert(has_stride<Mapping> == expected); > + } > + > +template<typename Layout> > + constexpr void > + test_has_stride_1d() > + { static_assert(has_stride<typename Layout::mapping<std::extents<int, > 1>>>); } > + > +template<typename Layout> > + constexpr void > + test_has_stride_2d() > + { > + using Extents = std::extents<int, 1, 2>; > + static_assert(has_stride<typename Layout::mapping<Extents>>); > + } > + > +// Check operator== > +template<typename Layout> > + constexpr void > + test_eq() > + { > + typename Layout::mapping<std::extents<int, 1, 2>> m1; > + typename Layout::mapping<std::extents<int, 2, 2>> m2; > + typename Layout::mapping<std::dextents<int, 2>> m3(m1); > + > + VERIFY(m1 == m1); > + VERIFY(m1 != m2); > + VERIFY(m1 == m3); > + VERIFY(m2 != m3); > + } > + > +template<typename Layout> > + constexpr void > + test_eq_zero() > + { > + typename Layout::mapping<std::extents<int, 0, 2>> m1; > + typename Layout::mapping<std::extents<int, 0, 2>> m2; > + typename Layout::mapping<std::extents<int, 2, 0>> m3; > + > + VERIFY(m1 == m2); > + VERIFY(m1 != m3); > + } > + > +template<typename M1, typename M2> > + concept has_op_eq = requires (M1 m1, M2 m2) > + { > + { m1 == m2 } -> std::same_as<bool>; > + { m2 == m1 } -> std::same_as<bool>; > + { m1 != m2 } -> std::same_as<bool>; > + { m2 != m1 } -> std::same_as<bool>; > + }; > + > +template<typename Layout> > + constexpr bool > + test_has_op_eq() > + { > + static_assert(!has_op_eq< > + typename Layout::mapping<std::extents<int, 1, 2>>, > + typename Layout::mapping<std::extents<int, 1>>>); > + > + static_assert(has_op_eq< > + typename Layout::mapping<std::extents<int, 1>>, > + typename Layout::mapping<std::extents<int, 1>>>); > + > + static_assert(has_op_eq< > + typename Layout::mapping<std::extents<int, 1>>, > + typename Layout::mapping<std::extents<int, 2>>>); > + return true; > + } > + > +template<typename Layout> > + constexpr bool > + test_mapping_all() > + { > + test_linear_index_all<Layout>(); > + test_required_span_size_all<Layout>(); > + test_stride_all<Layout>(); > + > + test_eq<Layout>(); > + test_eq_zero<Layout>(); > + return true; > + } > + > +template<typename Layout> > + constexpr void > + test_all() > + { > + static_assert(std::is_trivially_default_constructible_v<Layout>); > + static_assert(std::is_trivially_copyable_v<Layout>); > + static_assert(test_mapping_properties_all<Layout>()); > + > + test_mapping_all<Layout>(); > + static_assert(test_mapping_all<Layout>()); > + > + test_has_stride_0d<Layout>(); > + test_has_stride_1d<Layout>(); > + test_has_stride_2d<Layout>(); > + test_has_op_eq<Layout>(); > + } > + > +int > +main() > +{ > + test_all<std::layout_left>(); > + return 0; > +} > -- > 2.49.0 > >