[PATCH v1 1/3] libstdc++: Refactor mdspan tests [PR121061]
Tomasz Kaminski
tkaminsk@redhat.com
Thu Jul 17 14:04:20 GMT 2025
Also LGTM, thanks for moving int_like.h to mdspan.
Just pushed it to master.
On Wed, Jul 16, 2025 at 10:04 PM Jonathan Wakely <jwakely.gcc@gmail.com>
wrote:
>
>
> On Wed, 16 Jul 2025, 14:48 Luc Grosheintz, <luc.grosheintz@gmail.com>
> wrote:
>
>> PR121061 shows that the test coverage for custom integer types is
>> insufficient. Custom IndexTypes are passed to mdspan related objects in
>> one of two ways:
>>
>> * as a template parameter pack,
>> * or as an array/span.
>>
>> These two cases have different requirements on the (constness of) custom
>> IndexTypes. Therefore, the tests are restructured as follows:
>>
>> * allow testing with different custom integers,
>> * separate code that tests the two cases described above,
>> * use int_like.h for all tests with custom integers.
>>
>
> I like this approach, thanks.
>
> OK for trunk.
>
>
>
>> The affected tests are for:
>>
>> * creating extents, layout_stride::mapping and mdspan from
>> custom integers,
>>
>> * mapping::operator() and mdspan::operator[].
>>
>> PR libstdc++/121061
>>
>> libstdc++-v3/ChangeLog:
>>
>> * testsuite/23_containers/mdspan/extents/custom_integer.cc:
>> Enable checking with different custom integers. Improve
>> checking non-existence of overloads for incompatible custom
>> integers.
>> * testsuite/23_containers/mdspan/layouts/mapping.cc: ditto. Also
>> improve reuse of int_like.h.
>> * testsuite/23_containers/mdspan/layouts/stride.cc: ditto.
>> * testsuite/23_containers/mdspan/mdspan.cc: ditto.
>> * testsuite/23_containers/mdspan/extents/int_like.h: Rename (old
>> name).
>> * testsuite/23_containers/mdspan/int_like.h: Rename (new name).
>> (ThrowingInt): Add.
>> (NotIntLike): Add.
>>
>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>> ---
>> .../mdspan/extents/custom_integer.cc | 98 +++++++-----
>> .../23_containers/mdspan/extents/int_like.h | 30 ----
>> .../testsuite/23_containers/mdspan/int_like.h | 49 ++++++
>> .../23_containers/mdspan/layouts/mapping.cc | 110 +++++++-------
>> .../23_containers/mdspan/layouts/stride.cc | 20 +--
>> .../testsuite/23_containers/mdspan/mdspan.cc | 143 ++++++++++++------
>> 6 files changed, 264 insertions(+), 186 deletions(-)
>> delete mode 100644
>> libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
>> create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>>
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> index 404755bd5ac..4f631815b10 100644
>> ---
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> +++
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
>> @@ -2,7 +2,7 @@
>> #include <mdspan>
>>
>> #include <testsuite_hooks.h>
>> -#include "int_like.h"
>> +#include "../int_like.h"
>>
>> // Test construction from a custom integer-like object, that has
>> // no copy/move ctor or copy/move assignment operator.
>> @@ -12,51 +12,81 @@ constexpr size_t dyn = std::dynamic_extent;
>> static_assert(std::is_convertible_v<IntLike, int>);
>> static_assert(std::is_nothrow_constructible_v<int, IntLike>);
>>
>> -void
>> -test_shape(const auto& s2, const auto& s23)
>> -{
>> - std::extents<int, 2, 3> expected;
>> +template<typename Extents, bool Valid>
>> + void
>> + test_shape(const auto& shape)
>> + {
>> + static_assert(std::is_constructible_v<Extents, decltype(shape)> ==
>> Valid);
>>
>> - std::extents<int, 2, 3> e1(s23);
>> - VERIFY(e1 == expected);
>> + if constexpr (Valid)
>> + {
>> + std::extents<int, 2, 3> expected;
>> + Extents actual(shape);
>> + VERIFY(actual == expected);
>> + }
>> + }
>>
>> - std::extents<int, dyn, 3> e2(s2);
>> - VERIFY(e2 == expected);
>> +template<typename Int, bool Valid>
>> + void
>> + test_shape_all()
>> + {
>> + auto a2 = std::array<Int, 1>{Int(2)};
>> + auto s2 = std::span<Int, 1>(a2);
>>
>> - std::extents<int, dyn, 3> e3(s23);
>> - VERIFY(e3 == expected);
>> + auto a23 = std::array<Int, 2>{Int(2), Int(3)};
>> + auto s23 = std::span<Int, 2>(a23);
>>
>> - std::extents<int, dyn, dyn> e4(s23);
>> - VERIFY(e4 == expected);
>> -}
>> + auto check = [](const auto& dyn_exts, const auto& full_exts)
>> + {
>> + test_shape<std::extents<int, 2, 3>, Valid>(full_exts);
>> + test_shape<std::extents<int, dyn, 3>, Valid>(dyn_exts);
>> + test_shape<std::extents<int, dyn, 3>, Valid>(full_exts);
>> + test_shape<std::extents<int, dyn, dyn>, Valid>(full_exts);
>> + };
>>
>> -void
>> -test_pack()
>> -{
>> - std::extents<int, 2, 3> expected;
>> + check(a2, a23);
>> + check(s2, s23);
>> + }
>>
>> - std::extents<int, dyn, 3> e1(IntLike(2));
>> - VERIFY(e1 == expected);
>> +// Needed because is_constructible requires that Ints are move
>> constructible.
>> +template<typename Extents, typename... Ints>
>> + concept has_ctor = requires
>> + {
>> + { Extents(Ints(0)...) } -> std::same_as<Extents>;
>> + };
>>
>> - std::extents<int, dyn, 3> e2(IntLike(2), IntLike(3));
>> - VERIFY(e2 == expected);
>> +template<typename Int, bool Valid>
>> + void
>> + test_pack_all()
>> + {
>> + static_assert(has_ctor<std::extents<int, dyn, 3>, Int> == Valid);
>> + static_assert(has_ctor<std::extents<int, dyn, 3>, Int, Int> ==
>> Valid);
>> + static_assert(has_ctor<std::extents<int, dyn, dyn>, Int, Int> ==
>> Valid);
>>
>> - std::extents<int, dyn, dyn> e3(IntLike(2), IntLike(3));
>> - VERIFY(e3 == expected);
>> -}
>> + if constexpr (Valid)
>> + {
>> + std::extents<int, 2, 3> expected;
>> +
>> + std::extents<int, dyn, 3> e1(Int(2));
>> + VERIFY(e1 == expected);
>> +
>> + std::extents<int, dyn, 3> e2(Int(2), Int(3));
>> + VERIFY(e2 == expected);
>> +
>> + std::extents<int, dyn, dyn> e3(Int(2), Int(3));
>> + VERIFY(e3 == expected);
>> + }
>> + }
>>
>> int
>> main()
>> {
>> - auto a2 = std::array<IntLike, 1>{IntLike(2)};
>> - auto s2 = std::span<IntLike, 1>(a2);
>> -
>> - auto a23 = std::array<IntLike, 2>{IntLike(2), IntLike(3)};
>> - auto s23 = std::span<IntLike, 2>(a23);
>> -
>> - test_shape(a2, a23);
>> - test_shape(s2, s23);
>> - test_pack();
>> + test_shape_all<int, true>();
>> + test_shape_all<IntLike, true>();
>> + test_shape_all<ThrowingInt, false>();
>>
>> + test_pack_all<int, true>();
>> + test_pack_all<IntLike, true>();
>> + test_pack_all<ThrowingInt, false>();
>> return 0;
>> }
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
>> deleted file mode 100644
>> index f39f4cc9081..00000000000
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h
>> +++ /dev/null
>> @@ -1,30 +0,0 @@
>> -#ifndef TEST_MDSPAN_INT_LIKE_H
>> -#define TEST_MDSPAN_INT_LIKE_H
>> -
>> -class IntLike
>> -{
>> -public:
>> - explicit
>> - IntLike(int i)
>> - : _M_i(i)
>> - { }
>> -
>> - IntLike() = delete;
>> - IntLike(const IntLike&) = delete;
>> - IntLike(IntLike&&) = delete;
>> -
>> - const IntLike&
>> - operator=(const IntLike&) = delete;
>> -
>> - const IntLike&
>> - operator=(IntLike&&) = delete;
>> -
>> - constexpr
>> - operator int() const noexcept
>> - { return _M_i; }
>> -
>> -private:
>> - int _M_i;
>> -};
>> -
>> -#endif // TEST_MDSPAN_INT_LIKE_H
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> new file mode 100644
>> index 00000000000..ed45375f986
>> --- /dev/null
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
>> @@ -0,0 +1,49 @@
>> +#ifndef TEST_MDSPAN_INT_LIKE_H
>> +#define TEST_MDSPAN_INT_LIKE_H
>> +
>> +enum class CustomIndexKind
>> +{
>> + Const,
>> + Throwing,
>> +};
>> +
>> +template<CustomIndexKind Kind>
>> + class CustomIndexType
>> + {
>> + public:
>> + explicit
>> + CustomIndexType(int i)
>> + : _M_i(i)
>> + { }
>> +
>> + CustomIndexType() = delete;
>> + CustomIndexType(const CustomIndexType&) = delete;
>> + CustomIndexType(CustomIndexType&&) = delete;
>> +
>> + const CustomIndexType&
>> + operator=(const CustomIndexType&) = delete;
>> +
>> + const CustomIndexType&
>> + operator=(CustomIndexType&&) = delete;
>> +
>> + constexpr
>> + operator int() const noexcept
>> + requires (Kind == CustomIndexKind::Const)
>> + { return _M_i; }
>> +
>> + constexpr
>> + operator int() const
>> + requires (Kind == CustomIndexKind::Throwing)
>> + { return _M_i; }
>> +
>> + private:
>> + int _M_i;
>> + };
>> +
>> +using IntLike = CustomIndexType<CustomIndexKind::Const>;
>> +using ThrowingInt = CustomIndexType<CustomIndexKind::Throwing>;
>> +
>> +struct NotIntLike
>> +{ };
>> +
>> +#endif // TEST_MDSPAN_INT_LIKE_H
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> index 963c804a369..17f0c00acf2 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
>> @@ -1,6 +1,7 @@
>> // { dg-do run { target c++23 } }
>> #include <mdspan>
>>
>> +#include "../int_like.h"
>> #include <cstdint>
>> #include <testsuite_hooks.h>
>>
>> @@ -59,14 +60,13 @@ template<typename Mapping, size_t N>
>> return ret;
>> }
>>
>> -template<typename Mapping, typename... Indices>
>> +template<typename Int, 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);
>> + VERIFY(m(Int(i)...) == expected);
>> }
>>
>> template<typename Layout>
>> @@ -77,26 +77,26 @@ template<typename Layout>
>> VERIFY(m() == 0);
>> }
>>
>> -template<typename Layout>
>> +template<typename Layout, typename Int>
>> 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);
>> + test_linear_index<Int>(m, 0);
>> + test_linear_index<Int>(m, 1);
>> + test_linear_index<Int>(m, 4);
>> }
>>
>> -template<typename Layout>
>> +template<typename Layout, typename Int>
>> 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);
>> + test_linear_index<Int>(m, 0, 0);
>> + test_linear_index<Int>(m, 1, 0);
>> + test_linear_index<Int>(m, 0, 1);
>> + test_linear_index<Int>(m, 1, 1);
>> + test_linear_index<Int>(m, 2, 4);
>> }
>>
>> template<typename Layout>
>> @@ -141,44 +141,34 @@ template<>
>> }
>> };
>>
>> -template<typename Layout>
>> +template<typename Layout, typename Int>
>> 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);
>> + test_linear_index<Int>(m, 0, 0, 0);
>> + test_linear_index<Int>(m, 1, 0, 0);
>> + test_linear_index<Int>(m, 0, 1, 0);
>> + test_linear_index<Int>(m, 0, 0, 1);
>> + test_linear_index<Int>(m, 1, 1, 0);
>> + test_linear_index<Int>(m, 2, 4, 6);
>> }
>>
>> -struct IntLikeA
>> -{
>> - operator int()
>> - { return 0; }
>> -};
>> -
>> -struct IntLikeB
>> -{
>> - operator int() noexcept
>> - { return 0; }
>> -};
>> -
>> -struct NotIntLike
>> -{ };
>> +template<typename Mapping, typename... Ints>
>> + concept has_linear_index = requires (Mapping m)
>> + {
>> + { m(Ints(0)...) } -> std::same_as<typename Mapping::index_type>;
>> + };
>>
>> 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>);
>> + static_assert(has_linear_index<Mapping>);
>> + static_assert(!has_linear_index<Mapping, int>);
>> + static_assert(!has_linear_index<Mapping, IntLike>);
>> + static_assert(!has_linear_index<Mapping, NotIntLike>);
>> }
>>
>> template<typename Layout>
>> @@ -186,12 +176,13 @@ template<typename Layout>
>> 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>);
>> + static_assert(!has_linear_index<Mapping>);
>> + static_assert(has_linear_index<Mapping, int>);
>> + static_assert(has_linear_index<Mapping, double>);
>> + static_assert(has_linear_index<Mapping, IntLike>);
>> + static_assert(!has_linear_index<Mapping, ThrowingInt>);
>> + static_assert(!has_linear_index<Mapping, NotIntLike>);
>> + static_assert(!has_linear_index<Mapping, int, int>);
>> }
>>
>> template<typename Layout>
>> @@ -199,22 +190,23 @@ template<typename Layout>
>> 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>);
>> + static_assert(!has_linear_index<Mapping, int>);
>> + static_assert(has_linear_index<Mapping, int, int>);
>> + static_assert(has_linear_index<Mapping, double, double>);
>> + static_assert(has_linear_index<Mapping, IntLike, int>);
>> + static_assert(!has_linear_index<Mapping, ThrowingInt, int>);
>> + static_assert(!has_linear_index<Mapping, NotIntLike, int>);
>> + static_assert(!has_linear_index<Mapping, int, int, int>);
>> }
>>
>> -template<typename Layout>
>> +template<typename Layout, typename Int>
>> 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_linear_index_1d<Layout, Int>();
>> + test_linear_index_2d<Layout, Int>();
>> + test_linear_index_3d<Layout, Int>();
>> test_has_linear_index_0d<Layout>();
>> test_has_linear_index_1d<Layout>();
>> test_has_linear_index_2d<Layout>();
>> @@ -527,7 +519,13 @@ template<typename Layout>
>> constexpr bool
>> test_mapping_all()
>> {
>> - test_linear_index_all<Layout>();
>> + test_linear_index_all<Layout, uint8_t>();
>> + test_linear_index_all<Layout, int>();
>> + if !consteval
>> + {
>> + test_linear_index_all<Layout, IntLike>();
>> + }
>> +
>> test_required_span_size_all<Layout>();
>> test_stride_all<Layout>();
>>
>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> index c8af5c61254..1267306fb5c 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
>> @@ -1,6 +1,7 @@
>> // { dg-do run { target c++23 } }
>> #include <mdspan>
>>
>> +#include "../int_like.h"
>> #include <testsuite_hooks.h>
>>
>> constexpr size_t dyn = std::dynamic_extent;
>> @@ -42,21 +43,6 @@ test_ctor_default_stride_all()
>> 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()
>> @@ -77,8 +63,8 @@ test_stride_constructible_all()
>> 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, IntLike, 0, true>();
>> + test_stride_constructible<E0, E0, ThrowingInt, 0, false>();
>> test_stride_constructible<E0, E0, NotIntLike, 0, false>();
>> test_stride_constructible<E1, E1, int, 1, true>();
>> test_stride_constructible<E2, E1, int, 1, true>();
>> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> index a650fb19bdf..adabb0c6639 100644
>> --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
>> @@ -2,7 +2,7 @@
>> #include <mdspan>
>>
>> #include <testsuite_hooks.h>
>> -#include "extents/int_like.h"
>> +#include "int_like.h"
>> #include "layout_like.h"
>>
>> constexpr auto dyn = std::dynamic_extent;
>> @@ -317,32 +317,50 @@ test_from_accessor()
>> return true;
>> }
>>
>> -void
>> -test_from_int_like()
>> -{
>> - constexpr size_t n = 3*5*7;
>> - std::array<double, n> storage{};
>> +template<typename MDSpan, typename Pointer, typename... Ints>
>> + concept has_pack_ctor = requires
>> + {
>> + { MDSpan(Pointer{}, Ints(0)...) } -> std::same_as<MDSpan>;
>> + };
>>
>> - auto verify = [&](auto md)
>> - {
>> - VERIFY(md.data_handle() == storage.data());
>> - VERIFY(md.extent(0) == 3);
>> - VERIFY(md.extent(1) == 5);
>> - VERIFY(md.extent(2) == 7);
>> +template<typename CustomInt, bool ValidForPacks, bool ValidForArrays>
>> + constexpr bool
>> + test_from_int_like()
>> + {
>> + constexpr size_t n = 3*5*7;
>> + std::array<double, n> storage{};
>>
>> - VERIFY((md[IntLike(0), 0, IntLike(0)]) == 0.0);
>> - auto zero = std::array{IntLike(0), IntLike(0), IntLike(0)};
>> - auto zero_view = std::span<IntLike, 3>{zero};
>> - VERIFY((md[zero]) == 0.0);
>> - VERIFY((md[zero_view]) == 0.0);
>> - };
>> + auto verify = [&](auto md)
>> + {
>> + VERIFY(md.data_handle() == storage.data());
>> + VERIFY(md.extent(0) == 3);
>> + VERIFY(md.extent(1) == 5);
>> + VERIFY(md.extent(2) == 7);
>> + };
>>
>> - auto shape = std::array{IntLike(3), IntLike(5), IntLike(7)};
>> - auto shape_view = std::span<IntLike, 3>{shape};
>> - verify(std::mdspan(storage.data(), IntLike(3), 5, IntLike(7)));
>> - verify(std::mdspan(storage.data(), shape));
>> - verify(std::mdspan(storage.data(), shape_view));
>> -}
>> + static_assert(has_pack_ctor<std::mdspan<float, std::dextents<int,
>> 3>>,
>> + float*, CustomInt, int, CustomInt> == ValidForPacks);
>> +
>> + static_assert(std::is_constructible_v<
>> + std::mdspan<float, std::dextents<int, 3>>, float*,
>> + std::span<CustomInt, 3>> == ValidForArrays);
>> +
>> + static_assert(std::is_constructible_v<
>> + std::mdspan<float, std::dextents<int, 3>>, float*,
>> + std::array<CustomInt, 3>> == ValidForArrays);
>> +
>> + if constexpr (ValidForPacks)
>> + verify(std::mdspan(storage.data(), CustomInt(3), 5, CustomInt(7)));
>> +
>> + if constexpr (ValidForArrays)
>> + {
>> + auto shape = std::array{CustomInt(3), CustomInt(5), CustomInt(7)};
>> + auto shape_view = std::span<CustomInt, 3>{shape};
>> + verify(std::mdspan(storage.data(), shape));
>> + verify(std::mdspan(storage.data(), shape_view));
>> + }
>> + return true;
>> + }
>>
>> template<typename T, bool NothrowConstructible = true,
>> bool NothrowAssignable = true>
>> @@ -491,32 +509,53 @@ test_empty_all()
>> return true;
>> }
>>
>> -constexpr bool
>> -test_access()
>> +template<typename MDSpan, typename... Args>
>> +concept indexable = requires (MDSpan md, Args... args)
>> {
>> - using Extents = std::extents<int, 3, 5, 7>;
>> - auto exts = Extents{};
>> + { md[args...] } -> std::same_as<typename MDSpan::reference>;
>> +};
>>
>> - auto mapping = std::layout_left::mapping(exts);
>> - constexpr size_t n = mapping.required_span_size();
>> - std::array<double, n> storage{};
>> +template<typename Int, bool ValidForPacks, bool ValidForArrays>
>> + constexpr bool
>> + test_access()
>> + {
>> + using Extents = std::extents<int, 3, 5, 7>;
>> + auto exts = Extents{};
>>
>> - auto md = std::mdspan(storage.data(), mapping);
>> - static_assert(std::__mdspan::__mapping_alike<decltype(md)>);
>> + auto mapping = std::layout_left::mapping(exts);
>> + constexpr size_t n = mapping.required_span_size();
>> + std::array<double, n> storage{};
>>
>> - for(int i = 0; i < exts.extent(0); ++i)
>> - for(int j = 0; j < exts.extent(1); ++j)
>> - for(int k = 0; k < exts.extent(2); ++k)
>> - {
>> - std::array<int, 3> ijk{i, j, k};
>> - storage[mapping(i, j, k)] = 1.0;
>> - VERIFY((md[i, j, k]) == 1.0);
>> - VERIFY((md[ijk]) == 1.0);
>> - VERIFY((md[std::span(ijk)]) == 1.0);
>> - storage[mapping(i, j, k)] = 0.0;
>> - }
>> - return true;
>> -}
>> + auto md = std::mdspan(storage.data(), mapping);
>> + using MDSpan = decltype(md);
>> +
>> + for(int i = 0; i < exts.extent(0); ++i)
>> + for(int j = 0; j < exts.extent(1); ++j)
>> + for(int k = 0; k < exts.extent(2); ++k)
>> + {
>> + storage[mapping(i, j, k)] = 1.0;
>> + if constexpr (ValidForPacks)
>> + VERIFY((md[Int(i), Int(j), Int(k)]) == 1.0);
>> +
>> + if constexpr (ValidForArrays)
>> + {
>> + std::array<Int, 3> ijk{Int(i), Int(j), Int(k)};
>> + VERIFY((md[ijk]) == 1.0);
>> + VERIFY((md[std::span(ijk)]) == 1.0);
>> + }
>> + storage[mapping(i, j, k)] = 0.0;
>> + }
>> +
>> + if constexpr (!ValidForPacks)
>> + static_assert(!indexable<MDSpan, Int, int, Int>);
>> +
>> + if constexpr (!ValidForArrays)
>> + {
>> + static_assert(!indexable<MDSpan, std::array<Int, 3>>);
>> + static_assert(!indexable<MDSpan, std::span<Int, 3>>);
>> + }
>> + return true;
>> + }
>>
>> constexpr bool
>> test_swap()
>> @@ -650,14 +689,20 @@ main()
>> test_from_accessor();
>> static_assert(test_from_accessor());
>>
>> - test_from_int_like();
>> + test_from_int_like<int, true, true>();
>> + static_assert(test_from_int_like<int, true, true>());
>> + test_from_int_like<IntLike, true, true>();
>> + test_from_int_like<ThrowingInt, false, false>();
>> +
>> test_from_opaque_accessor();
>> test_from_base_class_accessor();
>> test_from_mapping_like();
>> static_assert(test_from_mapping_like());
>>
>> - test_access();
>> - static_assert(test_access());
>> + test_access<int, true, true>();
>> + static_assert(test_access<int, true, true>());
>> + test_access<IntLike, true, true>();
>> + test_access<ThrowingInt, false, false>();
>>
>> test_swap();
>> static_assert(test_swap());
>> --
>> 2.50.0
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250717/6bd989e4/attachment-0001.htm>
More information about the Libstdc++
mailing list