blob: 99de4015ef31c9649171d3c8114ba3b17acce3af [file] [log] [blame]
// { dg-do run { target c++23 } }
#include <mdspan>
#include <testsuite_hooks.h>
#include "../int_like.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;
static_assert(std::is_convertible_v<IntLike, int>);
static_assert(std::is_nothrow_constructible_v<int, IntLike>);
template<typename Extents, bool Valid>
void
test_shape(const auto& shape)
{
static_assert(std::is_constructible_v<Extents, decltype(shape)> == Valid);
if constexpr (Valid)
{
std::extents<int, 2, 3> expected;
Extents actual(shape);
VERIFY(actual == 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);
auto a23 = std::array<Int, 2>{Int(2), Int(3)};
auto s23 = std::span<Int, 2>(a23);
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);
};
check(a2, a23);
check(s2, s23);
}
// 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>;
};
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);
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()
{
test_shape_all<int, true>();
test_shape_all<IntLike, true>();
test_shape_all<ThrowingInt, false>();
test_shape_all<MutatingInt, false>();
test_shape_all<RValueInt, false>();
test_pack_all<int, true>();
test_pack_all<IntLike, true>();
test_pack_all<ThrowingInt, false>();
test_pack_all<MutatingInt, true>();
test_pack_all<RValueInt, true>();
return 0;
}