On Wed, Jun 4, 2025 at 5:45 PM Luc Grosheintz <luc.groshei...@gmail.com> wrote:
> > > On 6/4/25 15:38, Tomasz Kaminski wrote: > > On Wed, Jun 4, 2025 at 2:19 PM Tomasz Kaminski <tkami...@redhat.com> > wrote: > > > >> > >> > >> On Wed, Jun 4, 2025 at 2:05 PM Luc Grosheintz <luc.groshei...@gmail.com > > > >> wrote: > >> > >>> > >>> > >>> On 6/4/25 13:19, Tomasz Kaminski wrote: > >>>> Ah, sorry I got confused in the review suggestions, and latter when > >>>> checking the code. > >>>> What I meant is: > >>>> > >>>> Because the incoming strided_layout is required to be unique, > >>>> that implies that for each of strides are greater or equal to the > >>> extents. > >>>> As a consequence, other.required_span_size() is always greater than > >>> equal > >>>> to size of index_space, > >>>> so we can have static assert like: > >>>> static_assert(__mdspan::__representable_size<_OExtents, > index_type>, > >>>> "other.required_span_size() must be representable as > index_type"); > >>>> In here: > >>>> if constexpr (cmp_greater( > >>>> numeric_limits<typename > >>> _StridedMapping::index_type>::max(), > >>>> numeric_limits<index_type>::max())) > >>>> { > >>>> > static_assert(__mdspan::__representable_size<_OExtents, > >>>> index_type>, > >>>> "other.required_span_size() must be > representable > >>> as > >>>> index_type") > >>>> > >>> __glibcxx_assert(!cmp_less(numeric_limits<index_type>::max(), > >>>> > >>> __other.required_span_size())); > >>>> } > >>>> > >>> > >>> I would lift the static assertion above the `if constexpr` because > >>> that way we have to trust the other mapping less. > >>> > >> Sure, make sense. > >> > > Maybe we should add a comment, explaning why !__representable_size && > > !is_unique implies __other.required_span_size() > index_type. > > > > I just sent v6. Personally, I don't think that > > required_span_size >= extents size > > is a subtle statement. Maybe it's fine without? > Yes, we do not need to do another revision to add it. > > >> > >> > >>>> > >>>> > >>>> On Wed, Jun 4, 2025 at 1:09 PM Luc Grosheintz < > luc.groshei...@gmail.com > >>>> > >>>> wrote: > >>>> > >>>>> > >>>>> > >>>>> On 6/3/25 15:24, Tomasz Kaminski wrote: > >>>>>> On Fri, May 30, 2025 at 6:44 PM Luc Grosheintz < > >>> luc.groshei...@gmail.com > >>>>>> > >>>>>> wrote: > >>>>>> > >>>>>>> Implements the tests for layout_stride and for the features of the > >>> other > >>>>>>> two layouts that depend on layout_stride. > >>>>>>> > >>>>>>> libstdc++-v3/ChangeLog: > >>>>>>> > >>>>>>> * > >>> testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: > >>>>> Add > >>>>>>> tests for layout_stride. > >>>>>>> * testsuite/23_containers/mdspan/layouts/ctors.cc: Add > >>> test for > >>>>>>> layout_stride and the interaction with other layouts. > >>>>>>> * testsuite/23_containers/mdspan/layouts/mapping.cc: > Ditto. > >>>>>>> * testsuite/23_containers/mdspan/layouts/stride.cc: New > >>> test. > >>>>>>> > >>>>>>> Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> > >>>>>>> --- > >>>>>>> > >>>>>> LTGM. Only one comment regarding the tests that we could add. > >>>>>> > >>>>>>> .../mdspan/layouts/class_mandate_neg.cc | 3 + > >>>>>>> .../23_containers/mdspan/layouts/ctors.cc | 99 ++++ > >>>>>>> .../23_containers/mdspan/layouts/empty.cc | 1 + > >>>>>>> .../23_containers/mdspan/layouts/mapping.cc | 75 ++- > >>>>>>> .../23_containers/mdspan/layouts/stride.cc | 526 > >>> ++++++++++++++++++ > >>>>>>> 5 files changed, 703 insertions(+), 1 deletion(-) > >>>>>>> create mode 100644 > >>>>>>> libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.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 > >>>>>>> index 6469fa601e9..6862ed0c0ae 100644 > >>>>>>> --- > >>>>>>> > >>>>> > >>> > a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > >>>>>>> +++ > >>>>>>> > >>>>> > >>> > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc > >>>>>>> @@ -31,9 +31,12 @@ template<size_t Count, typename Layout, typename > >>>>>>> OLayout> > >>>>>>> > >>>>>>> A<std::layout_left> a_left; // { dg-error > >>>>> "required > >>>>>>> from" } > >>>>>>> A<std::layout_right> a_right; // { dg-error > >>>>> "required > >>>>>>> from" } > >>>>>>> +A<std::layout_stride> a_stride; // { dg-error > >>>>> "required > >>>>>>> from" } > >>>>>>> > >>>>>>> B<1, std::layout_left, std::layout_left> bll; // { dg-error > >>>>> "required > >>>>>>> here" } > >>>>>>> +B<2, std::layout_left, std::layout_stride> bls; // { dg-error > >>>>> "required > >>>>>>> here" } > >>>>>>> > >>>>>> With the message that we added to static assert to layout_stride > >>>>>> constructor: > >>>>>> >> "other.required_span_size() must be representable as > >>> index_type" > >>>>>> I believe you could add here: > >>>>>> B<2, std::layout_stride, std::layout_left> > >>>>>> And similarly for layout_right. > >>>>> > >>>>> I've tried (even before) and always failed miserably. Only good news > >>>>> is that the final > >>>>> > >>>>> // { dg-prune-output "must be representable as index_type" } > >>>>> > >>>>> isn't superfluous. I seem like the only string I can match against > >>>>> is the one associated with that line of code, in this case that's > >>>>> > >>>>> mdspan:773: error: static assertion failed: The size of > >>> OtherExtents > >>>>> must be representable as index_type > >>>>> [ ... ] > >>>>> class_mandate_neg.cc:40: note: synthesized method 'constexpr > B<4, > >>>>> std::layout_right, std::layout_stride>::B()' first required > here > >>>>> > >>>>> I unsure why you're saying that we added the message: > >>>>> > >>>>> "other.required_span_size() must be representable as index_type" > >>>>> > >>>>> to a static_assert, we added it to a __glibcxx_assert. The tests here > >>>>> are designed to trigger different assertions. > >>>>> > >>>>> "A" triggers: > >>>>> > >>>>> template<typename _Extents> > >>>>> class layout_*::mapping > >>>>> { > >>>>> public: > >>>>> // ... > >>>>> > >>>>> static_assert(__mdspan::__representable_size<extents_type, > >>>>> index_type>, > >>>>> "The size of extents_type must be representable as > >>> index_type"); > >>>>> > >>>>> > >>>>> "B" triggers: > >>>>> > >>>>> template<typename _OExtents> > >>>>> constexpr explicit > >>>>> mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) > >>> noexcept > >>>>> : _M_extents(__oexts) > >>>>> { > >>>>> static_assert(__mdspan::__representable_size<_OExtents, > >>> index_type>, > >>>>> "The size of OtherExtents must be representable as > >>> index_type"); > >>>>> > >>>>> We don't have tests that make __glibcxx_assert's fail. We could > >>> probably > >>>>> do it with constexpr variables with "dynamic" extents. > >>>>> > >>>>>> > >>>>>>> > >>>>>>> B<3, std::layout_right, std::layout_right> brr; // { dg-error > >>>>> "required > >>>>>>> here" } > >>>>>>> +B<4, std::layout_right, std::layout_stride> brs; // { dg-error > >>>>> "required > >>>>>>> here" } > >>>>>>> > >>>>>>> // { 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 > >>>>>>> index b0e03161874..695e887ca87 100644 > >>>>>>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > >>>>>>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc > >>>>>>> @@ -323,6 +323,104 @@ namespace from_left_or_right > >>>>>>> } > >>>>>>> } > >>>>>>> > >>>>>>> +// ctor: mapping(layout_stride::mapping<OExtents>) > >>>>>>> +namespace from_stride > >>>>>>> +{ > >>>>>>> + template<typename Mapping> > >>>>>>> + constexpr auto > >>>>>>> + strides(Mapping m) > >>>>>>> + { > >>>>>>> + constexpr auto rank = Mapping::extents_type::rank(); > >>>>>>> + std::array<typename Mapping::index_type, rank> s; > >>>>>>> + > >>>>>>> + if constexpr (rank > 0) > >>>>>>> + for(size_t i = 0; i < rank; ++i) > >>>>>>> + s[i] = m.stride(i); > >>>>>>> + return s; > >>>>>>> + } > >>>>>>> + > >>>>>>> + template<typename Layout, typename Extents, typename OExtents> > >>>>>>> + constexpr void > >>>>>>> + verify_convertible(OExtents oexts) > >>>>>>> + { > >>>>>>> + using Mapping = typename Layout::mapping<Extents>; > >>>>>>> + using OMapping = std::layout_stride::mapping<OExtents>; > >>>>>>> + > >>>>>>> + constexpr auto other = OMapping(oexts, > >>>>>>> strides(Mapping(Extents(oexts)))); > >>>>>>> + if constexpr (std::is_same_v<Layout, std::layout_right>) > >>>>>>> + ::verify_nothrow_convertible<Mapping>(other); > >>>>>>> + else > >>>>>>> + ::verify_convertible<Mapping>(other); > >>>>>>> + } > >>>>>>> + > >>>>>>> + template<typename Layout, typename Extents, typename OExtents> > >>>>>>> + constexpr void > >>>>>>> + verify_constructible(OExtents oexts) > >>>>>>> + { > >>>>>>> + using Mapping = typename Layout::mapping<Extents>; > >>>>>>> + using OMapping = std::layout_stride::mapping<OExtents>; > >>>>>>> + > >>>>>>> + constexpr auto other = OMapping(oexts, > >>>>>>> strides(Mapping(Extents(oexts)))); > >>>>>>> + if constexpr (std::is_same_v<Layout, std::layout_right>) > >>>>>>> + ::verify_nothrow_constructible<Mapping>(other); > >>>>>>> + else > >>>>>>> + ::verify_constructible<Mapping>(other); > >>>>>>> + } > >>>>>>> + > >>>>>>> + template<typename Layout> > >>>>>>> + constexpr bool > >>>>>>> + test_ctor() > >>>>>>> + { > >>>>>>> + assert_not_constructible< > >>>>>>> + typename Layout::mapping<std::extents<int>>, > >>>>>>> + std::layout_stride::mapping<std::extents<int, 1>>>(); > >>>>>>> + > >>>>>>> + assert_not_constructible< > >>>>>>> + typename Layout::mapping<std::extents<int, 1>>, > >>>>>>> + std::layout_stride::mapping<std::extents<int>>>(); > >>>>>>> + > >>>>>>> + assert_not_constructible< > >>>>>>> + typename Layout::mapping<std::extents<int, 2>>, > >>>>>>> + std::layout_stride::mapping<std::extents<int, 1>>>(); > >>>>>>> + > >>>>>>> + verify_convertible<Layout, > >>>>> std::extents<int>>(std::extents<int>{}); > >>>>>>> + > >>>>>>> + verify_convertible<Layout, std::extents<unsigned int>>( > >>>>>>> + std::extents<int>{}); > >>>>>>> + > >>>>>>> + // Rank == 0 doesn't check IndexType for convertibility. > >>>>>>> + verify_convertible<Layout, std::extents<int>>( > >>>>>>> + std::extents<unsigned int>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<int, 3>>( > >>>>>>> + std::extents<int, 3>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<unsigned int, 3>>( > >>>>>>> + std::extents<int, 3>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<int, 3>>( > >>>>>>> + std::extents<unsigned int, 3>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<int, 3, 5>>( > >>>>>>> + std::extents<int, 3, 5>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<unsigned int, 3, > >>> 5>>( > >>>>>>> + std::extents<int, 3, 5>{}); > >>>>>>> + > >>>>>>> + verify_constructible<Layout, std::extents<int, 3, 5>>( > >>>>>>> + std::extents<unsigned int, 3, 5>{}); > >>>>>>> + return true; > >>>>>>> + } > >>>>>>> + > >>>>>>> + template<typename Layout> > >>>>>>> + constexpr void > >>>>>>> + test_all() > >>>>>>> + { > >>>>>>> + test_ctor<Layout>(); > >>>>>>> + static_assert(test_ctor<Layout>()); > >>>>>>> + } > >>>>>>> +} > >>>>>>> + > >>>>>>> template<typename Layout> > >>>>>>> constexpr void > >>>>>>> test_all() > >>>>>>> @@ -330,6 +428,7 @@ template<typename Layout> > >>>>>>> default_ctor::test_all<Layout>(); > >>>>>>> from_extents::test_all<Layout>(); > >>>>>>> from_same_layout::test_all<Layout>(); > >>>>>>> + from_stride::test_all<Layout>(); > >>>>>>> } > >>>>>>> > >>>>>>> int > >>>>>>> diff --git > >>>>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc > >>>>>>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc > >>>>>>> index dc2a95ebbe6..d550c0a8e84 100644 > >>>>>>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc > >>>>>>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc > >>>>>>> @@ -64,5 +64,6 @@ main() > >>>>>>> { > >>>>>>> static_assert(test_all<std::layout_left>()); > >>>>>>> static_assert(test_all<std::layout_right>()); > >>>>>>> + static_assert(test_all<std::layout_stride>()); > >>>>>>> return 0; > >>>>>>> } > >>>>>>> diff --git > >>>>>>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > >>>>>>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > >>>>>>> index 4dc0db66865..963c804a369 100644 > >>>>>>> --- > a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > >>>>>>> +++ > b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc > >>>>>>> @@ -12,6 +12,7 @@ template<typename Layout, typename Extents> > >>>>>>> { > >>>>>>> using M = typename Layout::mapping<Extents>; > >>>>>>> static_assert(std::__mdspan::__is_extents<typename > >>>>> M::extents_type>); > >>>>>>> + static_assert(std::__mdspan::__mapping_alike<M>); > >>>>>>> static_assert(std::copyable<M>); > >>>>>>> static_assert(std::is_nothrow_move_constructible_v<M>); > >>>>>>> static_assert(std::is_nothrow_move_assignable_v<M>); > >>>>>>> @@ -30,6 +31,8 @@ template<typename Layout, typename Extents> > >>>>>>> > >>>>>>> static_assert(M::is_always_unique() && M::is_unique()); > >>>>>>> static_assert(M::is_always_strided() && M::is_strided()); > >>>>>>> + if constexpr (!std::is_same_v<Layout, std::layout_stride>) > >>>>>>> + static_assert(M::is_always_exhaustive() && > >>> M::is_exhaustive()); > >>>>>>> return true; > >>>>>>> } > >>>>>>> > >>>>>>> @@ -105,6 +108,39 @@ template<typename Layout> > >>>>>>> { return exts; } > >>>>>>> }; > >>>>>>> > >>>>>>> +template<> > >>>>>>> + struct MappingFactory<std::layout_stride> > >>>>>>> + { > >>>>>>> + template<typename Extents> > >>>>>>> + static constexpr std::layout_stride::mapping<Extents> > >>>>>>> + create(Extents exts) > >>>>>>> + { > >>>>>>> + if constexpr (Extents::rank() == 0) > >>>>>>> + { > >>>>>>> + auto strides = std::array<size_t, 0>{}; > >>>>>>> + return std::layout_stride::mapping(exts, strides); > >>>>>>> + } > >>>>>>> + else if constexpr (Extents::rank() == 1) > >>>>>>> + { > >>>>>>> + auto strides = std::array<size_t, 1>{2}; > >>>>>>> + return std::layout_stride::mapping(exts, strides); > >>>>>>> + } > >>>>>>> + else if constexpr (Extents::rank() == 2) > >>>>>>> + { > >>>>>>> + size_t m = exts.extent(1); > >>>>>>> + auto strides = std::array<size_t, 2>{3*m, 2}; > >>>>>>> + return std::layout_stride::mapping(exts, strides); > >>>>>>> + } > >>>>>>> + else if constexpr (Extents::rank() == 3) > >>>>>>> + { > >>>>>>> + size_t n = exts.extent(0); > >>>>>>> + size_t m = exts.extent(1); > >>>>>>> + auto strides = std::array<size_t, 3>{3*m, 2, 11*m*n}; > >>>>>>> + return std::layout_stride::mapping(exts, strides); > >>>>>>> + } > >>>>>>> + } > >>>>>>> + }; > >>>>>>> + > >>>>>>> template<typename Layout> > >>>>>>> constexpr void > >>>>>>> test_linear_index_3d() > >>>>>>> @@ -280,6 +316,16 @@ template<typename Layout> > >>>>>>> VERIFY(m.stride(0) == 1); > >>>>>>> } > >>>>>>> > >>>>>>> +template<> > >>>>>>> + constexpr void > >>>>>>> + test_stride_1d<std::layout_stride>() > >>>>>>> + { > >>>>>>> + std::array<int, 1> strides{13}; > >>>>>>> + std::layout_stride::mapping m(std::extents<int, 3>{}, > strides); > >>>>>>> + VERIFY(m.stride(0) == strides[0]); > >>>>>>> + VERIFY(m.strides() == strides); > >>>>>>> + } > >>>>>>> + > >>>>>>> template<typename Layout> > >>>>>>> constexpr void > >>>>>>> test_stride_2d(); > >>>>>>> @@ -302,6 +348,17 @@ template<> > >>>>>>> VERIFY(m.stride(1) == 1); > >>>>>>> } > >>>>>>> > >>>>>>> +template<> > >>>>>>> + constexpr void > >>>>>>> + test_stride_2d<std::layout_stride>() > >>>>>>> + { > >>>>>>> + std::array<int, 2> strides{13, 2}; > >>>>>>> + std::layout_stride::mapping m(std::extents<int, 3, 5>{}, > >>> strides); > >>>>>>> + VERIFY(m.stride(0) == strides[0]); > >>>>>>> + VERIFY(m.stride(1) == strides[1]); > >>>>>>> + VERIFY(m.strides() == strides); > >>>>>>> + } > >>>>>>> + > >>>>>>> template<typename Layout> > >>>>>>> constexpr void > >>>>>>> test_stride_3d(); > >>>>>>> @@ -326,6 +383,19 @@ template<> > >>>>>>> VERIFY(m.stride(2) == 1); > >>>>>>> } > >>>>>>> > >>>>>>> +template<> > >>>>>>> + constexpr void > >>>>>>> + test_stride_3d<std::layout_stride>() > >>>>>>> + { > >>>>>>> + std::dextents<int, 3> exts(3, 5, 7); > >>>>>>> + std::array<int, 3> strides{11, 2, 41}; > >>>>>>> + std::layout_stride::mapping<std::dextents<int, 3>> m(exts, > >>>>> strides); > >>>>>>> + VERIFY(m.stride(0) == strides[0]); > >>>>>>> + VERIFY(m.stride(1) == strides[1]); > >>>>>>> + VERIFY(m.stride(2) == strides[2]); > >>>>>>> + VERIFY(m.strides() == strides); > >>>>>>> + } > >>>>>>> + > >>>>>>> template<typename Layout> > >>>>>>> constexpr bool > >>>>>>> test_stride_all() > >>>>>>> @@ -347,7 +417,7 @@ template<typename Layout> > >>>>>>> test_has_stride_0d() > >>>>>>> { > >>>>>>> using Mapping = typename > Layout::mapping<std::extents<int>>; > >>>>>>> - constexpr bool expected = false; > >>>>>>> + constexpr bool expected = std::is_same_v<Layout, > >>>>> std::layout_stride>; > >>>>>>> static_assert(has_stride<Mapping> == expected); > >>>>>>> } > >>>>>>> > >>>>>>> @@ -488,8 +558,11 @@ main() > >>>>>>> { > >>>>>>> test_all<std::layout_left>(); > >>>>>>> test_all<std::layout_right>(); > >>>>>>> + test_all<std::layout_stride>(); > >>>>>>> > >>>>>>> test_has_op_eq<std::layout_right, std::layout_left, false>(); > >>>>>>> + test_has_op_eq<std::layout_right, std::layout_stride, true>(); > >>>>>>> + test_has_op_eq<std::layout_left, std::layout_stride, true>(); > >>>>>>> test_has_op_eq_peculiar(); > >>>>>>> return 0; > >>>>>>> } > >>>>>>> diff --git > >>>>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc > >>>>>>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc > >>>>>>> new file mode 100644 > >>>>>>> index 00000000000..c8af5c61254 > >>>>>>> --- /dev/null > >>>>>>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc > >>>>>>> @@ -0,0 +1,526 @@ > >>>>>>> +// { dg-do run { target c++23 } } > >>>>>>> +#include <mdspan> > >>>>>>> + > >>>>>>> +#include <testsuite_hooks.h> > >>>>>>> + > >>>>>>> +constexpr size_t dyn = std::dynamic_extent; > >>>>>>> + > >>>>>>> +template<typename MappingStride> > >>>>>>> + constexpr void > >>>>>>> + test_ctor_default_stride() > >>>>>>> + { > >>>>>>> + using Extents = typename MappingStride::extents_type; > >>>>>>> + MappingStride actual; > >>>>>>> + typename std::layout_right::mapping<Extents> expected; > >>>>>>> + > >>>>>>> + constexpr auto rank = MappingStride::extents_type::rank(); > >>>>>>> + if constexpr (rank > 0) > >>>>>>> + for(size_t i = 0; i < rank; ++i) > >>>>>>> + VERIFY(actual.stride(i) == expected.stride(i)); > >>>>>>> + } > >>>>>>> + > >>>>>>> +constexpr bool > >>>>>>> +test_ctor_default_stride_all() > >>>>>>> +{ > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::extents<int, 3>>>(); > >>>>>>> + > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::extents<int, 3, 5, 7>>>(); > >>>>>>> + > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::dextents<int, 3>>>(); > >>>>>>> + > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::extents<int, 0, 5, 7>>>(); > >>>>>>> + > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::extents<int, 3, dyn, > dyn>>>(); > >>>>>>> + > >>>>>>> + test_ctor_default_stride< > >>>>>>> + std::layout_stride::mapping<std::extents<int, dyn, dyn, > 3>>>(); > >>>>>>> + return true; > >>>>>>> +} > >>>>>>> + > >>>>>>> +struct IntLikeA > >>>>>>> +{ > >>>>>>> + operator int() > >>>>>>> + { return 0; } > >>>>>>> +}; > >>>>>>> + > >>>>>>> +struct IntLikeB > >>>>>>> +{ > >>>>>>> + operator int() noexcept > >>>>>>> + { return 0; } > >>>>>>> +}; > >>>>>>> + > >>>>>>> +struct NotIntLike > >>>>>>> +{ }; > >>>>>>> + > >>>>>>> +template<typename E, typename E_arg, typename T, size_t N, bool > >>>>> Expected> > >>>>>>> +constexpr void > >>>>>>> +test_stride_constructible() > >>>>>>> +{ > >>>>>>> + static_assert(std::is_nothrow_constructible_v< > >>>>>>> + std::layout_stride::mapping<E>, E_arg, std::span<T, N>> == > >>>>>>> Expected); > >>>>>>> + static_assert(std::is_nothrow_constructible_v< > >>>>>>> + std::layout_stride::mapping<E>, E_arg, std::array<T, N>> == > >>>>>>> Expected); > >>>>>>> + > >>>>> > static_assert(!std::is_constructible_v<std::layout_stride::mapping<E>, > >>>>>>> + E_arg>); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_stride_constructible_all() > >>>>>>> +{ > >>>>>>> + using E0 = std::extents<int>; > >>>>>>> + using E1 = std::extents<int, 2>; > >>>>>>> + using E2 = std::extents<int, dyn>; > >>>>>>> + > >>>>>>> + test_stride_constructible<E0, E0, int, 0, true>(); > >>>>>>> + test_stride_constructible<E0, E0, IntLikeA, 0, false>(); > >>>>>>> + test_stride_constructible<E0, E0, IntLikeB, 0, true>(); > >>>>>>> + test_stride_constructible<E0, E0, NotIntLike, 0, false>(); > >>>>>>> + test_stride_constructible<E1, E1, int, 1, true>(); > >>>>>>> + test_stride_constructible<E2, E1, int, 1, true>(); > >>>>>>> + test_stride_constructible<E1, E1, int, 2, false>(); > >>>>>>> + test_stride_constructible<E1, E0, int, 1, false>(); > >>>>>>> +} > >>>>>>> + > >>>>>>> +template<typename Extents, typename Shape> > >>>>>>> + constexpr void > >>>>>>> + test_ctor_shape_strides(Extents exts, Shape strides) > >>>>>>> + { > >>>>>>> + using M = std::layout_stride::mapping<Extents>; > >>>>>>> + M m(exts, strides); > >>>>>>> + > >>>>>>> + if constexpr (Extents::rank() > 0) > >>>>>>> + for(size_t i = 0; i < exts.rank(); ++i) > >>>>>>> + { > >>>>>>> + VERIFY(m.stride(i) == strides[i]); > >>>>>>> + VERIFY(m.extents().extent(i) == exts.extent(i)); > >>>>>>> + } > >>>>>>> + } > >>>>>>> + > >>>>>>> +constexpr bool > >>>>>>> +test_ctor_shape_stride_all() > >>>>>>> +{ > >>>>>>> + test_ctor_shape_strides(std::extents<int>{}, std::array<int, > >>> 0>{}); > >>>>>>> + test_ctor_shape_strides(std::extents<int, 2>{}, std::array<int, > >>>>> 1>{3}); > >>>>>>> + test_ctor_shape_strides(std::extents<int, 2, 4, 6>{}, > >>>>>>> + std::array<int, 3>{20, 5, 45}); > >>>>>>> + return true; > >>>>>>> +} > >>>>>>> + > >>>>>>> +template<typename Extents, std::array<bool, 2> Strided, > >>>>>>> + std::array<bool, 2> Unique, std::array<bool, 2> Exhautive, > >>>>>>> + typename Extents::index_type Offset = 0> > >>>>>>> + struct MappingLike > >>>>>>> + { > >>>>>>> + using extents_type = Extents; > >>>>>>> + using index_type = typename Extents::index_type; > >>>>>>> + > >>>>>>> + constexpr > >>>>>>> + MappingLike(extents_type extents, > >>>>>>> + std::array<index_type, Extents::rank()> strides) > >>>>>>> + : _extents(extents), _strides(strides) > >>>>>>> + { } > >>>>>>> + > >>>>>>> + static constexpr bool > >>>>>>> + is_always_strided() requires (Strided[0]) > >>>>>>> + { return Strided[1]; } > >>>>>>> + > >>>>>>> + static constexpr bool > >>>>>>> + is_always_unique() requires (Unique[0]) > >>>>>>> + { return Unique[1]; } > >>>>>>> + > >>>>>>> + static constexpr bool > >>>>>>> + is_always_exhaustive() requires (Exhautive[0]) > >>>>>>> + { return Exhautive[1]; } > >>>>>>> + > >>>>>>> + constexpr Extents > >>>>>>> + extents() const { return _extents; } > >>>>>>> + > >>>>>>> + constexpr index_type > >>>>>>> + stride(size_t i) const { return _strides[i]; } > >>>>>>> + > >>>>>>> + template<typename... Indices> > >>>>>>> + constexpr index_type > >>>>>>> + operator()(Indices... indices) const > >>>>>>> + { > >>>>>>> + if (empty()) > >>>>>>> + VERIFY(false); > >>>>>>> + > >>>>>>> + std::array<index_type, Extents::rank()> > ind_arr{indices...}; > >>>>>>> + index_type ret = Offset; > >>>>>>> + for(size_t i = 0; i < Extents::rank(); ++i) > >>>>>>> + ret += ind_arr[i]*_strides[i]; > >>>>>>> + return ret; > >>>>>>> + } > >>>>>>> + > >>>>>>> + private: > >>>>>>> + constexpr bool > >>>>>>> + empty() const > >>>>>>> + { > >>>>>>> + for (size_t i = 0; i < extents_type::rank(); ++i) > >>>>>>> + if (_extents.extent(i) == 0) > >>>>>>> + return true; > >>>>>>> + return false; > >>>>>>> + } > >>>>>>> + > >>>>>>> + Extents _extents; > >>>>>>> + std::array<index_type, Extents::rank()> _strides; > >>>>>>> + }; > >>>>>>> + > >>>>>>> + > >>>>>>> +template<size_t Rank> > >>>>>>> +struct ExtentLike > >>>>>>> +{ > >>>>>>> + using index_type = int; > >>>>>>> + > >>>>>>> + static constexpr size_t > >>>>>>> + rank() { return Rank; } > >>>>>>> +}; > >>>>>>> + > >>>>>>> + > >>>>>>> +template<typename E1> > >>>>>>> +constexpr void > >>>>>>> +test_mapping_like_constructible() > >>>>>>> +{ > >>>>>>> + using M = std::layout_stride::mapping<E1>; > >>>>>>> + using E2 = std::dextents<typename E1::index_type, E1::rank()>; > >>>>>>> + using E3 = std::dextents<typename E1::index_type, E1::rank() + > 1>; > >>>>>>> + using E4 = ExtentLike<E1::rank()>; > >>>>>>> + > >>>>>>> + constexpr auto TT = std::array{true, true}; > >>>>>>> + constexpr auto FT = std::array{false, true}; > >>>>>>> + constexpr auto TF = std::array{true, false}; > >>>>>>> + > >>>>>>> + static_assert(std::is_constructible_v<M, MappingLike<E1, TT, TT, > >>>>> TT>>); > >>>>>>> + static_assert(std::is_constructible_v<M, MappingLike<E2, TT, TT, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E3, TT, > TT, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E1, FT, > TT, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E1, TF, > TT, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, > FT, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, > TF, > >>>>> TT>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, > TT, > >>>>> FT>>); > >>>>>>> + static_assert(std::is_constructible_v<M, MappingLike<E1, TT, TT, > >>>>> TF>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E4, TT, > TT, > >>>>> TF>>); > >>>>>>> + static_assert(!std::is_constructible_v<M, MappingLike<E4, TT, > TT, > >>>>> TT>>); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_mapping_like_constructible_all() > >>>>>>> +{ > >>>>>>> + test_mapping_like_constructible<std::extents<int>>(); > >>>>>>> + test_mapping_like_constructible<std::extents<int, 2>>(); > >>>>>>> + test_mapping_like_constructible<std::extents<int, 2, 3>>(); > >>>>>>> +} > >>>>>>> + > >>>>>>> +template<typename E1, typename E2> > >>>>>>> +constexpr void > >>>>>>> +test_mapping_like_convertible() > >>>>>>> +{ > >>>>>>> + using M1 = std::layout_stride::mapping<E1>; > >>>>>>> + using M2 = std::layout_stride::mapping<E2>; > >>>>>>> + constexpr auto TT = std::array{true, true}; > >>>>>>> + > >>>>>>> + static_assert(!std::is_convertible_v<MappingLike<E1, TT, TT, > TT>, > >>>>> M1>); > >>>>>>> + static_assert(!std::is_convertible_v<MappingLike<E2, TT, TT, > TT>, > >>>>> M1>); > >>>>>>> + static_assert(!std::is_convertible_v<MappingLike<E1, TT, TT, > TT>, > >>>>> M2>); > >>>>>>> + > >>>>>>> + > >>> static_assert(std::is_convertible_v<std::layout_stride::mapping<E2>, > >>>>>>> M1>); > >>>>>>> + > static_assert(std::is_convertible_v<std::layout_left::mapping<E2>, > >>>>> M1>); > >>>>>>> + > >>> static_assert(std::is_convertible_v<std::layout_right::mapping<E2>, > >>>>>>> M1>); > >>>>>>> + > >>>>>>> + > >>> static_assert(!std::is_convertible_v<std::layout_stride::mapping<E1>, > >>>>>>> M2>); > >>>>>>> + > >>> static_assert(!std::is_convertible_v<std::layout_left::mapping<E1>, > >>>>>>> M2>); > >>>>>>> + > >>> static_assert(!std::is_convertible_v<std::layout_right::mapping<E1>, > >>>>>>> M2>); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_mapping_like_convertible_all() > >>>>>>> +{ > >>>>>>> + test_mapping_like_convertible<std::extents<unsigned int>, > >>>>>>> + std::extents<int>>(); > >>>>>>> + test_mapping_like_convertible<std::extents<unsigned int, 2>, > >>>>>>> + std::extents<int, 2>>(); > >>>>>>> + test_mapping_like_convertible<std::extents<int, dyn, 3>, > >>>>>>> + std::extents<int, 2, 3>>(); > >>>>>>> +} > >>>>>>> + > >>>>>>> +template<typename Extents> > >>>>>>> +constexpr void > >>>>>>> +test_ctor_stride_like(Extents exts, std::array<int, > Extents::rank()> > >>>>>>> strides) > >>>>>>> +{ > >>>>>>> + auto other_right = std::layout_right::mapping(exts); > >>>>>>> + auto other_left = std::layout_left::mapping(exts); > >>>>>>> + auto other_stride = std::layout_stride::mapping(exts, strides); > >>>>>>> + > >>>>>>> + VERIFY(std::layout_stride::mapping<Extents>(other_right) == > >>>>>>> other_right); > >>>>>>> + VERIFY(std::layout_stride::mapping<Extents>(other_left) == > >>>>> other_left); > >>>>>>> + VERIFY(std::layout_stride::mapping<Extents>(other_stride) == > >>>>>>> other_stride); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_ctor_stride_like_all() > >>>>>>> +{ > >>>>>>> + using E1 = std::extents<int>; > >>>>>>> + auto s1 = std::array<int, 0>{}; > >>>>>>> + test_ctor_stride_like(E1{}, s1); > >>>>>>> + > >>>>>>> + using E2 = std::extents<int, 3>; > >>>>>>> + auto s2 = std::array<int, 1>{2}; > >>>>>>> + test_ctor_stride_like(E2{}, s2); > >>>>>>> + > >>>>>>> + using E3 = std::extents<int, 3, 5, 7>; > >>>>>>> + auto s3 = std::array<int, 3>{5, 1, 15}; > >>>>>>> + test_ctor_stride_like(E3{}, s3); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr bool > >>>>>>> +test_ctor_strides_all() > >>>>>>> +{ > >>>>>>> + test_ctor_default_stride_all(); > >>>>>>> + test_ctor_shape_stride_all(); > >>>>>>> + test_ctor_stride_like_all(); > >>>>>>> + return true; > >>>>>>> +} > >>>>>>> + > >>>>>>> +// Check is_exhaustive. > >>>>>>> +template<typename Extents, typename Strides> > >>>>>>> + constexpr void > >>>>>>> + test_is_exhaustive(Extents extents, Strides strides, bool > >>> expected) > >>>>>>> + { > >>>>>>> + std::layout_stride::mapping<Extents> m(extents, strides); > >>>>>>> + VERIFY(m.is_exhaustive() == expected); > >>>>>>> + > >>>>>>> + bool always_exhaustive = extents.rank() == 0 || > >>>>>>> m.required_span_size() == 0; > >>>>>>> + VERIFY(m.is_always_exhaustive() == always_exhaustive); > >>>>>>> + } > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_zero_1d() > >>>>>>> +{ > >>>>>>> + std::extents<int, 0> extents; > >>>>>>> + test_is_exhaustive(extents, std::array{1}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{2}, true); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_zero_3d() > >>>>>>> +{ > >>>>>>> + std::extents<int, 3, 0, 7> extents; > >>>>>>> + > >>>>>>> + test_is_exhaustive(extents, std::array{1, 1, 1}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{1, 2*21, 2*3}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{7, 2*21, 1}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{1, 21, 3}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{7, 21, 1}, true); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_0d() > >>>>>>> +{ > >>>>>>> + std::extents<int> extents; > >>>>>>> + test_is_exhaustive(extents, std::array<int, 0>{}, true); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_1d() > >>>>>>> +{ > >>>>>>> + std::extents<int, 3> extents; > >>>>>>> + test_is_exhaustive(extents, std::array{1}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{3}, false); > >>>>>>> +} > >>>>>>> + > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_3d() > >>>>>>> +{ > >>>>>>> + std::extents<int, 3, dyn, 7> extents(5); > >>>>>>> + > >>>>>>> + test_is_exhaustive(extents, std::array{1, 3, 3*5}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{5*7, 1, 5}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{7, 3*7, 1}, true); > >>>>>>> + > >>>>>>> + test_is_exhaustive(extents, std::array{1, 3, 2*3*5}, false); > >>>>>>> + test_is_exhaustive(extents, std::array{2*5*7, 1, 2*5}, false); > >>>>>>> + test_is_exhaustive(extents, std::array{2*7, 2*3*7, 2}, false); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_is_exhaustive_ones() > >>>>>>> +{ > >>>>>>> + std::extents<int, 1, 1, 3, 1> extents; > >>>>>>> + test_is_exhaustive(extents, std::array{1, 1, 1, 1}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{1, 1, 1, 3}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{3, 3, 1, 3}, true); > >>>>>>> + test_is_exhaustive(extents, std::array{3, 1, 1, 3}, true); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr bool > >>>>>>> +test_is_exhaustive_all() > >>>>>>> +{ > >>>>>>> + test_is_exhaustive_zero_1d(); > >>>>>>> + test_is_exhaustive_zero_3d(); > >>>>>>> + test_is_exhaustive_ones(); > >>>>>>> + test_is_exhaustive_0d(); > >>>>>>> + test_is_exhaustive_1d(); > >>>>>>> + test_is_exhaustive_3d(); > >>>>>>> + return true; > >>>>>>> +} > >>>>>>> + > >>>>>>> +template<typename Extents, int Offset> > >>>>>>> + using OffsetMapping = MappingLike<Extents, {true, true}, {true, > >>>>> true}, > >>>>>>> + {true, false}, Offset>; > >>>>>>> + > >>>>>>> +template<typename Extents> > >>>>>>> + constexpr void > >>>>>>> + test_eq(Extents exts, > >>>>>>> + std::array<typename Extents::index_type, Extents::rank()> > >>>>>>> left_strides, > >>>>>>> + std::array<typename Extents::index_type, Extents::rank()> > >>>>>>> right_strides, > >>>>>>> + std::array<typename Extents::index_type, Extents::rank()> > >>>>>>> padded_strides) > >>>>>>> + { > >>>>>>> + using DExtents = std::dextents<int, Extents::rank()>; > >>>>>>> + > >>>>>>> + std::layout_left::mapping<Extents> ml; > >>>>>>> + std::layout_right::mapping<DExtents> mr(exts); > >>>>>>> + > >>>>>>> + std::layout_stride::mapping<Extents> msd; > >>>>>>> + std::layout_stride::mapping<Extents> msl(exts, left_strides); > >>>>>>> + std::layout_stride::mapping<Extents> msr(exts, right_strides); > >>>>>>> + std::layout_stride::mapping<Extents> msp(exts, > padded_strides); > >>>>>>> + > >>>>>>> + OffsetMapping<Extents, 0> mor{exts, right_strides}; > >>>>>>> + OffsetMapping<Extents, 0> mol{exts, left_strides}; > >>>>>>> + OffsetMapping<Extents, 0> mop{exts, padded_strides}; > >>>>>>> + OffsetMapping<Extents, 1> moo{exts, right_strides}; > >>>>>>> + > >>>>>>> + VERIFY(msd == mr); > >>>>>>> + VERIFY(msd == mor); > >>>>>>> + VERIFY(msd != msp); > >>>>>>> + VERIFY(msd != mop); > >>>>>>> + > >>>>>>> + VERIFY(msl == ml); > >>>>>>> + VERIFY(msl == mol); > >>>>>>> + VERIFY(msd != msp); > >>>>>>> + VERIFY(msl != mop); > >>>>>>> + > >>>>>>> + VERIFY(msp == mop); > >>>>>>> + VERIFY(msp != ml); > >>>>>>> + VERIFY(msp != mr); > >>>>>>> + > >>>>>>> + VERIFY(msd != moo); > >>>>>>> + } > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_eq_0d() > >>>>>>> +{ > >>>>>>> + using Extents = std::extents<int>; > >>>>>>> + Extents exts; > >>>>>>> + std::layout_left::mapping<Extents> ml; > >>>>>>> + std::layout_right::mapping<Extents> mr; > >>>>>>> + std::layout_stride::mapping<Extents> ms; > >>>>>>> + OffsetMapping<Extents, 0> mor{exts, {}}; > >>>>>>> + OffsetMapping<Extents, 1> moo{exts, {}}; > >>>>>>> + > >>>>>>> + VERIFY(ms == ml); > >>>>>>> + VERIFY(ms == mr); > >>>>>>> + VERIFY(ms == mor); > >>>>>>> + VERIFY(ms != moo); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_eq_1d() > >>>>>>> +{ > >>>>>>> + using Extents = std::extents<int, 2>; > >>>>>>> + auto exhaustive_strides = std::array{1}; > >>>>>>> + auto padded_strides = std::array{2}; > >>>>>>> + > >>>>>>> + test_eq(Extents{}, exhaustive_strides, exhaustive_strides, > >>>>>>> padded_strides); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_eq_2d() > >>>>>>> +{ > >>>>>>> + using Extents = std::extents<int, 1, 2>; > >>>>>>> + auto left_strides = std::array{1, 1}; > >>>>>>> + auto right_strides = std::array{2, 1}; > >>>>>>> + auto padded_strides = std::array{2, 8}; > >>>>>>> + > >>>>>>> + test_eq(Extents{}, left_strides, right_strides, padded_strides); > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_eq_zero() > >>>>>>> +{ > >>>>>>> + using Extents = std::extents<int, 0, 2>; > >>>>>>> + using Mapping = std::layout_stride::mapping<Extents>; > >>>>>>> + > >>>>>>> + Extents exts; > >>>>>>> + std::array<int, 2> sl{1, 5}; > >>>>>>> + std::array<int, 2> sr{5, 1}; > >>>>>>> + > >>>>>>> + Mapping m1(exts, sl); > >>>>>>> + Mapping m2(exts, sl); > >>>>>>> + Mapping m3(exts, sr); > >>>>>>> + OffsetMapping<Extents, 0> m4(exts, sl); > >>>>>>> + > >>>>>>> + VERIFY(m1 == m2); > >>>>>>> + VERIFY(m1 != m3); > >>>>>>> + VERIFY(m1 == m4); > >>>>>>> + > >>>>>>> +} > >>>>>>> + > >>>>>>> +constexpr bool > >>>>>>> +test_eq_all() > >>>>>>> +{ > >>>>>>> + test_eq_0d(); > >>>>>>> + test_eq_1d(); > >>>>>>> + test_eq_2d(); > >>>>>>> + test_eq_zero(); > >>>>>>> + return true; > >>>>>>> +} > >>>>>>> + > >>>>>>> +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>; > >>>>>>> + }; > >>>>>>> + > >>>>>>> +constexpr void > >>>>>>> +test_has_op_eq() > >>>>>>> +{ > >>>>>>> + using E1 = std::extents<int>; > >>>>>>> + using E2 = std::extents<int, 2>; > >>>>>>> + using E3 = std::extents<int, 1, 2>; > >>>>>>> + constexpr auto FT = std::array{false, true}; > >>>>>>> + > >>>>>>> + static_assert(!has_op_eq< > >>>>>>> + std::layout_stride::mapping<E1>, MappingLike<E1, FT, FT, > >>> FT>>); > >>>>>>> + > >>>>>>> + static_assert(!has_op_eq< > >>>>>>> + std::layout_stride::mapping<E2>, MappingLike<E2, FT, FT, > >>> FT>>); > >>>>>>> + > >>>>>>> + static_assert(!has_op_eq< > >>>>>>> + std::layout_stride::mapping<E3>, MappingLike<E3, FT, FT, > >>> FT>>); > >>>>>>> +} > >>>>>>> + > >>>>>>> +int > >>>>>>> +main() > >>>>>>> +{ > >>>>>>> + test_ctor_strides_all(); > >>>>>>> + static_assert(test_ctor_strides_all()); > >>>>>>> + test_mapping_like_convertible_all(); > >>>>>>> + test_mapping_like_constructible_all(); > >>>>>>> + test_stride_constructible_all(); > >>>>>>> + test_is_exhaustive_all(); > >>>>>>> + static_assert(test_is_exhaustive_all()); > >>>>>>> + test_eq_all(); > >>>>>>> + static_assert(test_eq_all()); > >>>>>>> + test_has_op_eq(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> -- > >>>>>>> 2.49.0 > >>>>>>> > >>>>>>> > >>>>>> > >>>>> > >>>>> > >>>> > >>> > >>> > > > >