116719cd0SHui Xie //===----------------------------------------------------------------------===//
216719cd0SHui Xie //
316719cd0SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
416719cd0SHui Xie // See https://llvm.org/LICENSE.txt for license information.
516719cd0SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
616719cd0SHui Xie //
716719cd0SHui Xie //===----------------------------------------------------------------------===//
816719cd0SHui Xie
916719cd0SHui Xie // <tuple>
1016719cd0SHui Xie
1116719cd0SHui Xie // template <class... Types>
1216719cd0SHui Xie // template <class... UTypes>
1316719cd0SHui Xie // constexpr explicit(see below) tuple<Types>::tuple(const
1416719cd0SHui Xie // tuple<UTypes...>&&);
1516719cd0SHui Xie //
1616719cd0SHui Xie // Constraints:
1716719cd0SHui Xie // sizeof...(Types) equals sizeof...(UTypes) &&
1816719cd0SHui Xie // (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...) is true &&
1916719cd0SHui Xie // (
2016719cd0SHui Xie // sizeof...(Types) is not 1 ||
2116719cd0SHui Xie // (
2216719cd0SHui Xie // !is_convertible_v<decltype(u), T> &&
2316719cd0SHui Xie // !is_constructible_v<T, decltype(u)> &&
2416719cd0SHui Xie // !is_same_v<T, U>
2516719cd0SHui Xie // )
2616719cd0SHui Xie // )
2716719cd0SHui Xie
2816719cd0SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
2916719cd0SHui Xie
3016719cd0SHui Xie #include <cassert>
3116719cd0SHui Xie #include <tuple>
3216719cd0SHui Xie
33*83ead2bbSHui Xie #include "copy_move_types.h"
3416719cd0SHui Xie #include "test_macros.h"
3516719cd0SHui Xie
3616719cd0SHui Xie // test: The expression inside explicit is equivalent to:
3716719cd0SHui Xie // !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)
3816719cd0SHui Xie static_assert(std::is_convertible_v<const std::tuple<ConstMove>&&, std::tuple<ConvertibleFrom<ConstMove>>>);
3916719cd0SHui Xie
4016719cd0SHui Xie static_assert(std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,
4116719cd0SHui Xie std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
4216719cd0SHui Xie
4316719cd0SHui Xie static_assert(
4416719cd0SHui Xie !std::is_convertible_v<const std::tuple<MutableCopy>&&, std::tuple<ExplicitConstructibleFrom<ConstMove>>>);
4516719cd0SHui Xie
4616719cd0SHui Xie static_assert(!std::is_convertible_v<const std::tuple<ConstMove, ConstMove>&&,
4716719cd0SHui Xie std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>);
4816719cd0SHui Xie
test()4916719cd0SHui Xie constexpr bool test() {
5016719cd0SHui Xie // test implicit conversions.
5116719cd0SHui Xie // sizeof...(Types) == 1
5216719cd0SHui Xie {
5316719cd0SHui Xie const std::tuple<ConstMove> t1{1};
5416719cd0SHui Xie std::tuple<ConvertibleFrom<ConstMove>> t2 = std::move(t1);
5516719cd0SHui Xie assert(std::get<0>(t2).v.val == 1);
5616719cd0SHui Xie }
5716719cd0SHui Xie
5816719cd0SHui Xie // test implicit conversions.
5916719cd0SHui Xie // sizeof...(Types) > 1
6016719cd0SHui Xie {
6116719cd0SHui Xie const std::tuple<ConstMove, int> t1{1, 2};
6216719cd0SHui Xie std::tuple<ConvertibleFrom<ConstMove>, int> t2 = std::move(t1);
6316719cd0SHui Xie assert(std::get<0>(t2).v.val == 1);
6416719cd0SHui Xie assert(std::get<1>(t2) == 2);
6516719cd0SHui Xie }
6616719cd0SHui Xie
6716719cd0SHui Xie // test explicit conversions.
6816719cd0SHui Xie // sizeof...(Types) == 1
6916719cd0SHui Xie {
7016719cd0SHui Xie const std::tuple<ConstMove> t1{1};
7116719cd0SHui Xie std::tuple<ExplicitConstructibleFrom<ConstMove>> t2{std::move(t1)};
7216719cd0SHui Xie assert(std::get<0>(t2).v.val == 1);
7316719cd0SHui Xie }
7416719cd0SHui Xie
7516719cd0SHui Xie // test explicit conversions.
7616719cd0SHui Xie // sizeof...(Types) > 1
7716719cd0SHui Xie {
7816719cd0SHui Xie const std::tuple<ConstMove, int> t1{1, 2};
7916719cd0SHui Xie std::tuple<ExplicitConstructibleFrom<ConstMove>, int> t2{std::move(t1)};
8016719cd0SHui Xie assert(std::get<0>(t2).v.val == 1);
8116719cd0SHui Xie assert(std::get<1>(t2) == 2);
8216719cd0SHui Xie }
8316719cd0SHui Xie
8416719cd0SHui Xie // test constraints
8516719cd0SHui Xie
8616719cd0SHui Xie // sizeof...(Types) != sizeof...(UTypes)
8716719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<int, int>, const std::tuple<int>&&>);
8816719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<int, int, int>, const std::tuple<int, int>&&>);
8916719cd0SHui Xie
9016719cd0SHui Xie // !(is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...)
9116719cd0SHui Xie static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::tuple<int, int>&&>);
9216719cd0SHui Xie
9316719cd0SHui Xie // sizeof...(Types) == 1 && other branch of "||" satisfied
9416719cd0SHui Xie {
9516719cd0SHui Xie const std::tuple<TracedCopyMove> t1{};
9616719cd0SHui Xie std::tuple<ConvertibleFrom<TracedCopyMove>> t2{std::move(t1)};
9716719cd0SHui Xie assert(constMoveCtrCalled(std::get<0>(t2).v));
9816719cd0SHui Xie }
9916719cd0SHui Xie
10016719cd0SHui Xie // sizeof...(Types) == 1 && is_same_v<T, U>
10116719cd0SHui Xie {
10216719cd0SHui Xie const std::tuple<TracedCopyMove> t1{};
10316719cd0SHui Xie std::tuple<TracedCopyMove> t2{t1};
10416719cd0SHui Xie assert(!constMoveCtrCalled(std::get<0>(t2)));
10516719cd0SHui Xie }
10616719cd0SHui Xie
10716719cd0SHui Xie // sizeof...(Types) != 1
10816719cd0SHui Xie {
10916719cd0SHui Xie const std::tuple<TracedCopyMove, TracedCopyMove> t1{};
11016719cd0SHui Xie std::tuple<TracedCopyMove, TracedCopyMove> t2{std::move(t1)};
11116719cd0SHui Xie assert(constMoveCtrCalled(std::get<0>(t2)));
11216719cd0SHui Xie }
11316719cd0SHui Xie
11416719cd0SHui Xie // These two test points cause gcc to ICE
11516719cd0SHui Xie #if !defined(TEST_COMPILER_GCC)
11616719cd0SHui Xie // sizeof...(Types) == 1 && is_convertible_v<decltype(u), T>
11716719cd0SHui Xie {
11816719cd0SHui Xie const std::tuple<CvtFromConstTupleRefRef> t1{};
11916719cd0SHui Xie std::tuple<ConvertibleFrom<CvtFromConstTupleRefRef>> t2{std::move(t1)};
12016719cd0SHui Xie assert(!constMoveCtrCalled(std::get<0>(t2).v));
12116719cd0SHui Xie }
12216719cd0SHui Xie
12316719cd0SHui Xie // sizeof...(Types) == 1 && is_constructible_v<decltype(u), T>
12416719cd0SHui Xie {
12516719cd0SHui Xie const std::tuple<ExplicitCtrFromConstTupleRefRef> t1{};
12616719cd0SHui Xie std::tuple<ConvertibleFrom<ExplicitCtrFromConstTupleRefRef>> t2{std::move(t1)};
12716719cd0SHui Xie assert(!constMoveCtrCalled(std::get<0>(t2).v));
12816719cd0SHui Xie }
12916719cd0SHui Xie #endif
13016719cd0SHui Xie
13116719cd0SHui Xie return true;
13216719cd0SHui Xie }
13316719cd0SHui Xie
main(int,char **)13416719cd0SHui Xie int main(int, char**) {
13516719cd0SHui Xie test();
13616719cd0SHui Xie static_assert(test());
13716719cd0SHui Xie return 0;
13816719cd0SHui Xie }
139