1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <tuple>
10
11// template <class... Types>
12// template <class... UTypes>
13// constexpr explicit(see below) tuple<Types>::tuple(tuple<UTypes...>&);
14//
15// Constraints:
16// sizeof...(Types) equals sizeof...(UTypes) &&
17// (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...) is true &&
18// (
19// sizeof...(Types) is not 1 ||
20// (
21// !is_convertible_v<decltype(u), T> &&
22// !is_constructible_v<T, decltype(u)> &&
23// !is_same_v<T, U>
24// )
25// )
26
27// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
28
29#include <cassert>
30#include <tuple>
31
32#include "copy_move_types.h"
33#include "test_macros.h"
34
35// test: The expression inside explicit is equivalent to:
36// !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)
37static_assert(std::is_convertible_v<std::tuple<MutableCopy>&, std::tuple<ConvertibleFrom<MutableCopy>>>);
38
39static_assert(std::is_convertible_v<std::tuple<MutableCopy, MutableCopy>&,
40 std::tuple<ConvertibleFrom<MutableCopy>, ConvertibleFrom<MutableCopy>>>);
41
42static_assert(!std::is_convertible_v<std::tuple<MutableCopy>&, std::tuple<ExplicitConstructibleFrom<MutableCopy>>>);
43
44static_assert(!std::is_convertible_v<std::tuple<MutableCopy, MutableCopy>&,
45 std::tuple<ConvertibleFrom<MutableCopy>, ExplicitConstructibleFrom<MutableCopy>>>);
46
47constexpr bool test() {
48 // test implicit conversions.
49 // sizeof...(Types) == 1
50 {
51 std::tuple<MutableCopy> t1{1};
52 std::tuple<ConvertibleFrom<MutableCopy>> t2 = t1;
53 assert(std::get<0>(t2).v.val == 1);
54 }
55
56 // test implicit conversions.
57 // sizeof...(Types) > 1
58 {
59 std::tuple<MutableCopy, int> t1{1, 2};
60 std::tuple<ConvertibleFrom<MutableCopy>, int> t2 = t1;
61 assert(std::get<0>(t2).v.val == 1);
62 assert(std::get<1>(t2) == 2);
63 }
64
65 // test explicit conversions.
66 // sizeof...(Types) == 1
67 {
68 std::tuple<MutableCopy> t1{1};
69 std::tuple<ExplicitConstructibleFrom<MutableCopy>> t2{t1};
70 assert(std::get<0>(t2).v.val == 1);
71 }
72
73 // test explicit conversions.
74 // sizeof...(Types) > 1
75 {
76 std::tuple<MutableCopy, int> t1{1, 2};
77 std::tuple<ExplicitConstructibleFrom<MutableCopy>, int> t2{t1};
78 assert(std::get<0>(t2).v.val == 1);
79 assert(std::get<1>(t2) == 2);
80 }
81
82 // test constraints
83
84 // sizeof...(Types) != sizeof...(UTypes)
85 static_assert(!std::is_constructible_v<std::tuple<int, int>, std::tuple<int>&>);
86 static_assert(!std::is_constructible_v<std::tuple<int>, std::tuple<int, int>&>);
87 static_assert(!std::is_constructible_v<std::tuple<int, int, int>, std::tuple<int, int>&>);
88
89 // !(is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...)
90 static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, std::tuple<int, int>&>);
91
92 // sizeof...(Types) == 1 && other branch of "||" satisfied
93 {
94 std::tuple<TracedCopyMove> t1{};
95 std::tuple<ConvertibleFrom<TracedCopyMove>> t2{t1};
96 assert(nonConstCopyCtrCalled(std::get<0>(t2).v));
97 }
98
99 // sizeof...(Types) == 1 && is_same_v<T, U>
100 {
101 std::tuple<TracedCopyMove> t1{};
102 std::tuple<TracedCopyMove> t2{t1};
103 assert(!nonConstCopyCtrCalled(std::get<0>(t2)));
104 }
105
106 // sizeof...(Types) != 1
107 {
108 std::tuple<TracedCopyMove, TracedCopyMove> t1{};
109 std::tuple<TracedCopyMove, TracedCopyMove> t2{t1};
110 assert(nonConstCopyCtrCalled(std::get<0>(t2)));
111 }
112
113 // These two test points cause gcc to ICE
114#if !defined(TEST_COMPILER_GCC)
115 // sizeof...(Types) == 1 && is_convertible_v<decltype(u), T>
116 {
117 std::tuple<CvtFromTupleRef> t1{};
118 std::tuple<ConvertibleFrom<CvtFromTupleRef>> t2{t1};
119 assert(!nonConstCopyCtrCalled(std::get<0>(t2).v));
120 }
121
122 // sizeof...(Types) == 1 && is_constructible_v<decltype(u), T>
123 {
124 std::tuple<ExplicitCtrFromTupleRef> t1{};
125 std::tuple<ConvertibleFrom<ExplicitCtrFromTupleRef>> t2{t1};
126 assert(!nonConstCopyCtrCalled(std::get<0>(t2).v));
127 }
128#endif
129 return true;
130}
131
132int main(int, char**) {
133 test();
134 static_assert(test());
135 return 0;
136}
137

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_non_const_copy.pass.cpp