A prior commit added std::extents, this commit adds the tests. The bulk is focussed on testing the constructors. These are split into three groups:
1. the ctor from other extents and the copy ctor, 2. the ctor from a pack of integer-like objects, 3. the ctor from shapes, i.e. span and array. For each group check that the ctor: * produces an object with the expected values for extent, * is implicit if and only if required, * is constexpr, * doesn't change the rank of the extent. libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/extents/assign.cc: New test. * testsuite/23_containers/mdspan/extents/class_properties.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_copy.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_copy_constexpr.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_ints.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_ints_constexpr.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_shape_all_extents.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_shape_constexpr.cc: New test. * testsuite/23_containers/mdspan/extents/ctor_shape_dynamic_extents.cc: New test. * testsuite/23_containers/mdspan/extents/custom_integer.cc: New test. * testsuite/23_containers/mdspan/extents/deduction_guide.cc: New test. * testsuite/23_containers/mdspan/extents/dextents.cc: New test. * testsuite/23_containers/mdspan/extents/extent.cc: New test. * testsuite/23_containers/mdspan/extents/ops_eq.cc: New test. Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> --- .../23_containers/mdspan/extents/assign.cc | 29 ++++++ .../mdspan/extents/class_properties.cc | 62 +++++++++++++ .../23_containers/mdspan/extents/ctor_copy.cc | 75 +++++++++++++++ .../mdspan/extents/ctor_copy_constexpr.cc | 20 ++++ .../23_containers/mdspan/extents/ctor_ints.cc | 58 ++++++++++++ .../mdspan/extents/ctor_ints_constexpr.cc | 12 +++ .../mdspan/extents/ctor_shape_all_extents.cc | 61 +++++++++++++ .../mdspan/extents/ctor_shape_constexpr.cc | 23 +++++ .../extents/ctor_shape_dynamic_extents.cc | 91 +++++++++++++++++++ .../mdspan/extents/custom_integer.cc | 87 ++++++++++++++++++ .../mdspan/extents/deduction_guide.cc | 34 +++++++ .../23_containers/mdspan/extents/dextents.cc | 11 +++ .../23_containers/mdspan/extents/extent.cc | 24 +++++ .../23_containers/mdspan/extents/ops_eq.cc | 58 ++++++++++++ 14 files changed, 645 insertions(+) create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/assign.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/class_properties.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy_constexpr.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints_constexpr.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_all_extents.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_constexpr.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_dynamic_extents.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/deduction_guide.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/dextents.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/extent.cc create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/ops_eq.cc diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/assign.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/assign.cc new file mode 100644 index 00000000000..3bc32361a7b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/assign.cc @@ -0,0 +1,29 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr auto dyn = std::dynamic_extent; + +static_assert(std::is_nothrow_assignable_v<std::extents<int, dyn, 2>, + std::extents<int, 1, 2>>); + +int +main() +{ + auto e1 = std::extents<int, 1, 2>(); + auto e2 = std::extents<int, 1, 2>(); + + e2 = e1; + VERIFY(e2 == e1); + + auto e5 = std::extents<int, 1, dyn>(); + e5 = e1; + VERIFY(e5 == e1); + + auto e3 = std::extents<int, dyn, dyn>(1, 2); + auto e4 = std::extents<int, dyn, dyn>(3, 4); + e3 = e4; + VERIFY(e3 == e4); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_properties.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_properties.cc new file mode 100644 index 00000000000..548900a7f44 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_properties.cc @@ -0,0 +1,62 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#include <type_traits> + +constexpr auto dyn = std::dynamic_extent; + +// Check class traits. +static_assert(std::regular<std::extents<int>>); +static_assert(std::regular<std::extents<int, 1>>); +static_assert(std::regular<std::extents<int, dyn>>); + +static_assert(std::is_trivially_copyable_v<std::extents<int>>); +static_assert(std::is_trivially_copyable_v<std::extents<int, 1>>); +static_assert(std::is_trivially_copyable_v<std::extents<int, dyn>>); + +// Check member typedefs. +static_assert(std::is_same_v<std::extents<int, 1, 2>::rank_type, size_t>); + +static_assert(std::is_unsigned_v<std::extents<int, 2>::size_type>); +static_assert(std::is_unsigned_v<std::extents<unsigned int, 2>::size_type>); + +static_assert(std::is_same_v<std::extents<char, 2>::index_type, char>); +static_assert(std::is_same_v<std::extents<int, 2>::index_type, int>); +static_assert(std::is_same_v<std::extents<unsigned int, 2>::index_type, + unsigned int>); + +// Check `rank`. +static_assert(std::extents<int, 1>::rank() == 1); +static_assert(std::extents<int, dyn>::rank() == 1); +static_assert(std::extents<int, 2, dyn>::rank() == 2); + +// Check `rank_dynamic`. +static_assert(std::extents<int, 1>::rank_dynamic() == 0); +static_assert(std::extents<int, dyn>::rank_dynamic() == 1); +static_assert(std::extents<int, 2, dyn>::rank_dynamic() == 1); +static_assert(std::extents<int, dyn, dyn>::rank_dynamic() == 2); + +template<class T, size_t... Extents> + constexpr bool + check_rank_return_types() + { + auto e = std::extents<T, Extents...>(); + return std::is_same_v<decltype(e.rank()), size_t> + && std::is_same_v<decltype(e.rank_dynamic()), size_t>; + } + +static_assert(check_rank_return_types<int, 1>()); + +// Check that the static extents don't take up space. +static_assert(sizeof(std::extents<int, 1, dyn>) == sizeof(int)); +static_assert(sizeof(std::extents<char, 1, dyn>) == sizeof(char)); + +template<typename Extents> +class Container +{ + int dummy; + [[no_unique_address]] std::extents<size_t> b0; +}; + +static_assert(sizeof(Container<std::extents<char, 1, 2>>) == sizeof(int)); +static_assert(sizeof(Container<std::extents<size_t, 1, 2>>) == sizeof(int)); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc new file mode 100644 index 00000000000..44eeab2ef22 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc @@ -0,0 +1,75 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> +#include <type_traits> + +// Test the copy ctor and the ctor from other extents. + +constexpr auto dyn = std::dynamic_extent; + +// Not constructible +static_assert(!std::is_constructible_v<std::extents<int>, + std::extents<int, 1>>); + +static_assert(!std::is_constructible_v<std::extents<int, 1, 1>, + std::extents<int, 1>>); + +static_assert(!std::is_constructible_v<std::extents<int, dyn>, + std::extents<int, dyn, dyn>>); + +static_assert(!std::is_constructible_v<std::extents<int, 2, 2>, + std::extents<int, 1, 2>>); + +// Nothrow constructible +static_assert(std::is_nothrow_constructible_v<std::extents<int, 1>, + std::extents<unsigned int, dyn>>); +static_assert(std::is_nothrow_constructible_v<std::extents<unsigned int, dyn>, + std::extents<int, 1>>); + +// Implicit conversion +static_assert(!std::is_convertible_v<std::extents<unsigned int>, + std::extents<int>>); +static_assert(std::is_convertible_v<std::extents<int>, + std::extents<unsigned int>>); + +static_assert(!std::is_convertible_v<std::extents<unsigned int, 1>, + std::extents<int, 1>>); +static_assert(std::is_convertible_v<std::extents<int, 1>, + std::extents<unsigned int, 1>>); + +static_assert(!std::is_convertible_v<std::extents<int, dyn>, + std::extents<int, 1>>); +static_assert(std::is_convertible_v<std::extents<int, 1>, + std::extents<int, dyn>>); + +static_assert(!std::is_convertible_v<std::extents<unsigned int, 1>, + std::extents<int, dyn>>); +static_assert(std::is_convertible_v<std::extents<int, 1>, + std::extents<unsigned int, dyn>>); + +template<class T, size_t ... Extents, class Other> + void + test_ctor(const Other& other) + { + auto e = std::extents<T, Extents...>(other); + VERIFY(e == other); + } + +int +main() +{ + auto e0 = std::extents<int>(); + test_ctor<int>(e0); + + auto e1 = std::extents<int, 1, 2, 3>(); + test_ctor<int, 1, 2, 3>(e1); + test_ctor<int, 1, dyn, 3>(e1); + test_ctor<unsigned int, 1, dyn, 3>(e1); + + auto e2 = std::extents<unsigned int, 1, dyn, 3>{1, 2, 3}; + test_ctor<int, 1, 2, 3>(e2); + test_ctor<int, 1, dyn, 3>(e2); + test_ctor<int, 1, dyn, dyn>(e2); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy_constexpr.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy_constexpr.cc new file mode 100644 index 00000000000..49fa023c354 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy_constexpr.cc @@ -0,0 +1,20 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +// Test that the ctor from other extents is constexpr. + +constexpr auto dyn = std::dynamic_extent; + +constexpr std::extents<int> e0; +constexpr std::extents<int> e1 = e0; + +constexpr std::extents<int, 1> e2; +constexpr std::extents<int, 1> e3 = e2; +static_assert(e3 == e2); + +constexpr std::extents<int, dyn> e4 = e2; +static_assert(e4 == e2); + +constexpr std::extents<int, 3, 5> e5; +constexpr std::extents<int, dyn, 5> e6 = e5; +static_assert(e6 == e5); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc new file mode 100644 index 00000000000..3b23787ca15 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc @@ -0,0 +1,58 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr auto dyn = std::dynamic_extent; + +template<class Lhs, class Rhs> + void + verify(const Lhs& lhs, const Rhs& rhs) + { VERIFY(lhs == rhs); } + +class A {}; + +// Not constructible if the number of integer-like arguments isn't either +// rank() or rank_dynamic(). +static_assert(!std::is_constructible_v<std::extents<int>, int>); +static_assert(!std::is_constructible_v<std::extents<int, dyn, dyn>, int>); +static_assert(!std::is_constructible_v<std::extents<int, 1, dyn, 3>, int, int>); + +// Not constructible from non integer-like objects. +static_assert(!std::is_constructible_v<std::extents<int, 1>, int, A>); + +// No implicit conversion from integer-like objects. +template<typename Extent, typename... OExtents> + constexpr bool + is_explicit() + { + return std::is_nothrow_constructible_v<Extent, OExtents...> + && !std::is_convertible_v<Extent, OExtents...>; + } + +static_assert(is_explicit<std::extents<int, 1>, int>()); +static_assert(is_explicit<std::extents<int, 1>, unsigned int>()); +static_assert(is_explicit<std::extents<unsigned int, 1>, int>()); + +int +main() +{ + auto expected = std::extents<int, 1, 2, 3>(1, 2, 3); + + // From all extents. + verify(std::extents<int, 1, 2, 3>(1, 2, 3), expected); + verify(std::extents<int, dyn, 2, 3>(1, 2, 3), expected); + verify(std::extents<int, dyn, 2, dyn>(1, 2, 3), expected); + + verify(std::extents<int, 1, 2, 3>{1, 2, 3}, expected); + verify(std::extents<int, dyn, 2, 3>{1, 2, 3}, expected); + verify(std::extents<int, dyn, 2, dyn>{1, 2, 3}, expected); + + // From only dynamic extents. + verify(std::extents<int, dyn, 2, 3>(1), expected); + verify(std::extents<int, dyn, 2, dyn>(1, 3), expected); + + verify(std::extents<int, dyn, 2, 3>{1}, expected); + verify(std::extents<int, dyn, 2, dyn>{1, 3}, expected); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints_constexpr.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints_constexpr.cc new file mode 100644 index 00000000000..11f1520c652 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints_constexpr.cc @@ -0,0 +1,12 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +constexpr auto dyn = std::dynamic_extent; + +constexpr auto e0 = std::extents<int, 1, 2>(1, 2); +constexpr auto e1 = std::extents<int, 1, dyn>(2); +constexpr auto e3 = std::extents<int, dyn, dyn>(1, 2); + +constexpr auto e4 = std::extents<int, 1, 2>{1, 2}; +constexpr auto e5 = std::extents<int, 1, dyn>{2}; +constexpr auto e6 = std::extents<int, dyn, dyn>{1, 2}; diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_all_extents.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_all_extents.cc new file mode 100644 index 00000000000..78d2b22bb40 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_all_extents.cc @@ -0,0 +1,61 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr auto dyn = std::dynamic_extent; + +static_assert(std::is_nothrow_constructible_v<std::extents<int, 1, 2>, + std::array<int, 2>>); +static_assert(std::is_nothrow_constructible_v<std::extents<int, 1, 2>, + std::span<int, 2>>); + +// Not constructibe if the size of the shape isn't rank() or rank_dynamic(). +static_assert(!std::is_constructible_v<std::extents<int, 1, 2>, + std::array<int, 1>>); +static_assert(!std::is_constructible_v<std::extents<int, dyn, dyn>, + std::array<int, 1>>); + +template<typename Lhs, typename Rhs> + void + verify(const Lhs& lhs, const Rhs& rhs) + { VERIFY(lhs == rhs); } + +void +test_common_shapes() +{ + auto array = std::array<int, 3>{1, 2, 3}; + auto span_const = std::span<const int, 3>(array); + auto span = std::span<int, 3>(array); + + auto check = [](auto shape) + { + auto expected = std::extents<int, 1, 2, 3>(); + verify(std::extents<int, 1, dyn, 3>(shape), expected); + verify(std::extents<int, dyn, dyn, dyn>(shape), expected); + verify(std::extents<int, 1, 2, 3>(shape), expected); + }; + + check(array); + check(span); + check(span_const); +} + +void +test_empty_shapes() +{ + auto shape = std::array<int, 0>(); + auto span = std::span<int, 0>(shape); + + auto expected = std::extents<int>(); + verify(std::extents<int>(shape), expected); + verify(std::extents<int>(span), expected); +} + +int +main() +{ + test_common_shapes(); + test_empty_shapes(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_constexpr.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_constexpr.cc new file mode 100644 index 00000000000..8abe069c8c6 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_constexpr.cc @@ -0,0 +1,23 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +constexpr auto dyn = std::dynamic_extent; + +constexpr auto a0 = std::array<int, 0>{}; +constexpr auto a1 = std::array<int, 1>{2}; +constexpr auto a2 = std::array<int, 2>{1, 2}; + +constexpr auto e0 = std::extents<int, 1, 2>(a0); +constexpr auto e1 = std::extents<int, 1, dyn>(a1); +constexpr auto e2 = std::extents<int, 1, 2>(a2); +constexpr auto e3 = std::extents<int, dyn, dyn>(a2); + +constexpr auto s0 = std::span<const int, 0>(a0); +constexpr auto s1 = std::span<const int, 1>(a1); +constexpr auto s2 = std::span<const int, 2>(a2); + +constexpr auto e4 = std::extents<int, 1, 2>(s0); +constexpr auto e5 = std::extents<int, 1, dyn>(s1); +constexpr auto e6 = std::extents<int, 1, 2>(s2); +constexpr auto e7 = std::extents<int, dyn, dyn>(s2); + diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_dynamic_extents.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_dynamic_extents.cc new file mode 100644 index 00000000000..f02f21bbb25 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape_dynamic_extents.cc @@ -0,0 +1,91 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr size_t dyn = std::dynamic_extent; + +template<typename Extent, typename T, size_t N> + constexpr bool + constructible() + { + return std::is_nothrow_constructible_v<Extent, std::array<T, N>> + && std::is_nothrow_constructible_v<Extent, std::span<T, N>>; + } + +template<typename Extent, typename T, size_t N> + constexpr bool + convertible() + { + return std::is_convertible_v<std::array<T, N>, Extent> + && std::is_convertible_v<std::span<T, N>, Extent>; + } + +template<typename Extent, typename T, size_t N> + constexpr bool + not_convertible() + { + return !std::is_convertible_v<std::array<T, N>, Extent> + && !std::is_convertible_v<std::span<T, N>, Extent>; + } + +static_assert(constructible<std::extents<int>, int, 0>()); +static_assert(convertible<std::extents<int>, int, 0>()); +static_assert(convertible<std::extents<unsigned int>, int, 0>()); +static_assert(convertible<std::extents<int>, unsigned int, 0>()); + +static_assert(constructible<std::extents<int, 1, dyn>, int, 1>()); +static_assert(convertible<std::extents<int, 1, dyn>, int, 1>()); +static_assert(convertible<std::extents<unsigned int, 1, dyn>, int, 1>()); +static_assert(convertible<std::extents<int, 1, dyn>, unsigned int, 1>()); + +static_assert(constructible<std::extents<int, 1, dyn>, int, 2>()); +static_assert(not_convertible<std::extents<int, 1, dyn>, int, 2>()); +static_assert(not_convertible<std::extents<unsigned int, 1, dyn>, int, 2>()); +static_assert(not_convertible<std::extents<int, 1, dyn>, unsigned int, 2>()); + +// Non-integer, but convertible. +static_assert(constructible<std::extents<int, dyn>, double, 1>()); +static_assert(convertible<std::extents<int, dyn>, double, 1>()); + +template<typename Extents, typename Shape> + void + test_ctor(const Shape& shape) + { + Extents e = shape; + + VERIFY(e.rank_dynamic() == shape.size()); + + size_t di = 0; + for(size_t i = 0; i < e.rank(); ++i) + if(e.static_extent(i) == dyn) + VERIFY(e.extent(i) == shape[di++]); + } + +template<typename Extents, typename T, size_t N> + void + test_all_shape_types(std::array<T, N> shape) + { + test_ctor<Extents>(shape); + test_ctor<Extents>(std::span<T, N>(shape)); + test_ctor<Extents>(std::span<const T, N>(shape)); + } + +void +test_common_shapes() +{ + auto s = std::array<int, 0>{}; + auto s2 = std::array<int, 1>{2}; + auto s123 = std::array<int, 3>{1, 2, 3}; + + test_all_shape_types<std::extents<int, 1, dyn, 3>>(s2); + test_all_shape_types<std::extents<int, dyn, dyn, dyn>>(s123); + test_all_shape_types<std::extents<int, 1, 2, 3>>(s); +} + +int +main() +{ + test_common_shapes(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc new file mode 100644 index 00000000000..2907ad12ae7 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc @@ -0,0 +1,87 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +// Test construction from a custom integer-like object, that has +// no copy/move ctor or copy/move assignment operator. + +constexpr size_t dyn = std::dynamic_extent; + +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; +}; + +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; + + std::extents<int, 2, 3> e1(s23); + VERIFY(e1 == expected); + + std::extents<int, dyn, 3> e2(s2); + VERIFY(e2 == expected); + + std::extents<int, dyn, 3> e3(s23); + VERIFY(e3 == expected); + + std::extents<int, dyn, dyn> e4(s23); + VERIFY(e4 == expected); +} + +void +test_pack() +{ + std::extents<int, 2, 3> expected; + + std::extents<int, dyn, 3> e1(IntLike(2)); + VERIFY(e1 == expected); + + std::extents<int, dyn, 3> e2(IntLike(2), IntLike(3)); + VERIFY(e2 == expected); + + std::extents<int, dyn, dyn> e3(IntLike(2), IntLike(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(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/deduction_guide.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/deduction_guide.cc new file mode 100644 index 00000000000..974fa48febd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/deduction_guide.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#include <type_traits> + +constexpr auto dyn = std::dynamic_extent; + +constexpr auto e0 = std::extents(); +static_assert(std::is_same_v<decltype(e0), const std::dextents<size_t, 0>>); +static_assert(e0 == std::extents<size_t>()); + +constexpr auto e1 = std::extents(1); +static_assert(std::is_same_v<decltype(e1), const std::dextents<size_t, 1>>); +static_assert(e1 == std::extents<size_t, 1>()); + +constexpr auto e2 = std::extents(1.0, 2.0f); +static_assert(std::is_same_v<decltype(e2), const std::dextents<size_t, 2>>); +static_assert(e2 == std::extents<size_t, 1, 2>()); + +constexpr auto e3 = std::extents(int(1), char(2), size_t(3)); +static_assert(std::is_same_v<decltype(e3), const std::dextents<size_t, 3>>); +static_assert(e3 == std::extents<size_t, 1, 2, 3>()); + +class A {}; + +template<typename... Extents> + concept deducible = requires + { + { std::extents(Extents{}...) } + -> std::convertible_to<std::dextents<size_t, sizeof...(Extents)>>; + }; + +static_assert(deducible<int>); +static_assert(!deducible<A, A>); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/dextents.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/dextents.cc new file mode 100644 index 00000000000..31544373c72 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/dextents.cc @@ -0,0 +1,11 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#include <type_traits> + +constexpr auto dyn = std::dynamic_extent; + +static_assert(std::is_same_v<std::dextents<int, 0>, std::extents<int>>); +static_assert(std::is_same_v<std::dextents<int, 1>, std::extents<int, dyn>>); +static_assert(std::is_same_v<std::dextents<int, 5>, + std::extents<int, dyn, dyn, dyn, dyn, dyn>>); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extent.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extent.cc new file mode 100644 index 00000000000..1993fa31fc6 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extent.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +constexpr auto dyn = std::dynamic_extent; + +static_assert(std::extents<int, 1, 2>::static_extent(0) == 1); +static_assert(std::extents<int, 1, 2>::static_extent(1) == 2); + +static_assert(std::extents<int, 1, dyn>::static_extent(0) == 1); +static_assert(std::extents<int, 1, dyn>::static_extent(1) == dyn); + +static_assert(std::extents<int, dyn, dyn>::static_extent(0) == dyn); +static_assert(std::extents<int, dyn, dyn>::static_extent(1) == dyn); + +constexpr std::extents<int, 1, 2> e0; +static_assert(e0.extent(0) == 1 && e0.extent(1) == 2); + +constexpr std::extents<int, 1, dyn> e1(2); +static_assert(e1.extent(0) == 1 && e1.extent(1) == 2); + +constexpr std::extents<int, 1, dyn> e2(2); +static_assert(e2.extent(0) == 1 && e2.extent(1) == 2); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ops_eq.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ops_eq.cc new file mode 100644 index 00000000000..4a1b0641d9d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ops_eq.cc @@ -0,0 +1,58 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> + +template<class Lhs, class Rhs> + void + test_ops_eq(const Lhs& lhs, const Rhs& rhs, bool expected) + { + VERIFY((lhs == rhs) == expected); + VERIFY((lhs != rhs) == !expected); + } + +constexpr auto dyn = std::dynamic_extent; + +static_assert(std::extents<int, 1, 2, 3>() == std::extents<int, 1, 2, 3>()); +static_assert(std::extents<int, 1, 2, 3>() != std::extents<int, 1, 2>()); +static_assert(std::extents<int, 1, 2, 3>() == std::extents<int, 1, dyn, 3>(2)); +static_assert(std::extents<int, 1, 2, 3>() != std::extents<int, 1, dyn, 3>(3)); + +void +test_rank_zero() +{ + auto e1 = std::extents<int>(); + auto e2 = std::extents<int>(); + auto e3 = std::extents<unsigned int>(); + + test_ops_eq(e1, e2, true); + test_ops_eq(e1, e3, true); +} + +void +test_common() +{ + auto e1 = std::extents<int, 1, 2, 3>(); + auto e2 = std::extents<int, 1, 2, 3>(); + auto e3 = std::extents<int, 1, dyn, 3>(2); + auto e4 = std::extents<int, 1, dyn, 3>(3); + + auto e5 = std::extents<int, 1>(); + auto e6 = std::extents<int, 1, 3, 3>(); + + test_ops_eq(e1, e2, true); + test_ops_eq(e1, e3, true); + test_ops_eq(e1, e4, false); + + test_ops_eq(e1, e5, false); + test_ops_eq(e1, e6, false); + test_ops_eq(e3, e6, false); +} + +int +main() +{ + test_rank_zero(); + test_common(); + return 0; +} -- 2.48.1