mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00

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
122 lines
2.9 KiB
C++
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;
|
|
}
|