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....@gmail.com> wrote: > > > On Wed, 16 Jul 2025, 14:48 Luc Grosheintz, <luc.groshei...@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.groshei...@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 >> >>