Files
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_move.pass.cpp
Eric Fiselier 78af2bfb2f Fix tuple's conditionally explicit constructors for very weird user
types.

It seems some people like to write types that can explicitly convert
to anything, but cannot be used to explicitly construct anything.

This patch makes tuple tolerate such types, as is required
by the standard.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@365074 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-03 19:21:40 +00:00

122 lines
2.9 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// <tuple>
// template <class... Types> class tuple;
// template <class... UTypes> tuple(tuple<UTypes...>&& u);
// UNSUPPORTED: c++98, c++03
#include <tuple>
#include <string>
#include <memory>
#include <cassert>
#include "test_macros.h"
struct Explicit {
int value;
explicit Explicit(int x) : value(x) {}
};
struct Implicit {
int value;
Implicit(int x) : value(x) {}
};
struct B
{
int id_;
explicit B(int i) : id_(i) {}
virtual ~B() {}
};
struct D
: B
{
explicit D(int i) : B(i) {}
};
struct BonkersBananas {
template <class T>
operator T() &&;
template <class T, class = void>
explicit operator T() && = delete;
};
void test_bonkers_bananas_conversion() {
using ReturnType = std::tuple<int, int>;
static_assert(std::is_convertible<BonkersBananas, ReturnType>(), "");
static_assert(!std::is_constructible<ReturnType, BonkersBananas>(), "");
}
int main(int, char**)
{
{
typedef std::tuple<long> T0;
typedef std::tuple<long long> T1;
T0 t0(2);
T1 t1 = std::move(t0);
assert(std::get<0>(t1) == 2);
}
{
typedef std::tuple<long, char> T0;
typedef std::tuple<long long, int> T1;
T0 t0(2, 'a');
T1 t1 = std::move(t0);
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1) == int('a'));
}
{
typedef std::tuple<long, char, D> T0;
typedef std::tuple<long long, int, B> T1;
T0 t0(2, 'a', D(3));
T1 t1 = std::move(t0);
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1) == int('a'));
assert(std::get<2>(t1).id_ == 3);
}
{
D d(3);
typedef std::tuple<long, char, D&> T0;
typedef std::tuple<long long, int, B&> T1;
T0 t0(2, 'a', d);
T1 t1 = std::move(t0);
d.id_ = 2;
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1) == int('a'));
assert(std::get<2>(t1).id_ == 2);
}
{
typedef std::tuple<long, char, std::unique_ptr<D>> T0;
typedef std::tuple<long long, int, std::unique_ptr<B>> T1;
T0 t0(2, 'a', std::unique_ptr<D>(new D(3)));
T1 t1 = std::move(t0);
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1) == int('a'));
assert(std::get<2>(t1)->id_ == 3);
}
{
std::tuple<int> t1(42);
std::tuple<Explicit> t2(std::move(t1));
assert(std::get<0>(t2).value == 42);
}
{
std::tuple<int> t1(42);
std::tuple<Implicit> t2 = std::move(t1);
assert(std::get<0>(t2).value == 42);
}
return 0;
}