[PATCH v5 7/8] libstdc++: Add tests for layout_stride.
Luc Grosheintz
luc.grosheintz@gmail.com
Wed Jun 4 15:45:46 GMT 2025
On 6/4/25 15:38, Tomasz Kaminski wrote:
> On Wed, Jun 4, 2025 at 2:19 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>>
>>
>> On Wed, Jun 4, 2025 at 2:05 PM Luc Grosheintz <luc.grosheintz@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?
>>
>>
>>>>
>>>>
>>>> On Wed, Jun 4, 2025 at 1:09 PM Luc Grosheintz <luc.grosheintz@gmail.com
>>>>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On 6/3/25 15:24, Tomasz Kaminski wrote:
>>>>>> On Fri, May 30, 2025 at 6:44 PM Luc Grosheintz <
>>> luc.grosheintz@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.grosheintz@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
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>
More information about the Libstdc++
mailing list