#include <cassert>
#include <tuple>
#include "copy_move_types.h"
#include "test_macros.h"
static_assert(std::is_convertible_v<const std::tuple<ConstMove>&&, std::tuple<ConvertibleFrom<ConstMove>>>);
static_assert(std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,
std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
static_assert(
!std::is_convertible_v<const std::tuple<MutableCopy>&&, std::tuple<ExplicitConstructibleFrom<ConstMove>>>);
static_assert(!std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,
std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>);
constexpr bool test() {
{
const std::tuple<ConstMove> t1{1};
std::tuple<ConvertibleFrom<ConstMove>> t2 = std::move(t1);
assert(std::get<0>(t2).v.val == 1);
}
{
const std::tuple<ConstMove, int> t1{1, 2};
std::tuple<ConvertibleFrom<ConstMove>, int> t2 = std::move(t1);
assert(std::get<0>(t2).v.val == 1);
assert(std::get<1>(t2) == 2);
}
{
const std::tuple<ConstMove> t1{1};
std::tuple<ExplicitConstructibleFrom<ConstMove>> t2{std::move(t1)};
assert(std::get<0>(t2).v.val == 1);
}
{
const std::tuple<ConstMove, int> t1{1, 2};
std::tuple<ExplicitConstructibleFrom<ConstMove>, int> t2{std::move(t1)};
assert(std::get<0>(t2).v.val == 1);
assert(std::get<1>(t2) == 2);
}
static_assert(!std::is_constructible_v<std::tuple<int, int>, const std::tuple<int>&&>);
static_assert(!std::is_constructible_v<std::tuple<int, int, int>, const std::tuple<int, int>&&>);
static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::tuple<int, int>&&>);
{
const std::tuple<TracedCopyMove> t1{};
std::tuple<ConvertibleFrom<TracedCopyMove>> t2{std::move(t1)};
assert(constMoveCtrCalled(std::get<0>(t2).v));
}
{
const std::tuple<TracedCopyMove> t1{};
std::tuple<TracedCopyMove> t2{t1};
assert(!constMoveCtrCalled(std::get<0>(t2)));
}
{
const std::tuple<TracedCopyMove, TracedCopyMove> t1{};
std::tuple<TracedCopyMove, TracedCopyMove> t2{std::move(t1)};
assert(constMoveCtrCalled(std::get<0>(t2)));
}
#if !defined(TEST_COMPILER_GCC)
{
const std::tuple<CvtFromConstTupleRefRef> t1{};
std::tuple<ConvertibleFrom<CvtFromConstTupleRefRef>> t2{std::move(t1)};
assert(!constMoveCtrCalled(std::get<0>(t2).v));
}
{
const std::tuple<ExplicitCtrFromConstTupleRefRef> t1{};
std::tuple<ConvertibleFrom<ExplicitCtrFromConstTupleRefRef>> t2{std::move(t1)};
assert(!constMoveCtrCalled(std::get<0>(t2).v));
}
#endif
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}