xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/const_move_pair.pass.cpp (revision 83ead2bbc5e14ca1beb776c062ebc36c38e8bb1c)
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 U1, class U2>
13 // constexpr explicit(see below) tuple<Types...>::tuple(const pair<U1, U2>&& u);
14 
15 // Constraints:
16 // - sizeof...(Types) is 2 and
17 // - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
18 // - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
19 
20 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
21 
22 #include <cassert>
23 #include <tuple>
24 #include <utility>
25 
26 #include "copy_move_types.h"
27 
28 // test constraints
29 // sizeof...(Types) == 2
30 static_assert(std::is_constructible_v<std::tuple<ConstMove, int>, const std::pair<ConstMove, int>&&>);
31 
32 static_assert(!std::is_constructible_v<std::tuple<ConstMove>, const std::pair<ConstMove, int>&&>);
33 
34 static_assert(!std::is_constructible_v<std::tuple<ConstMove, int, int>, const std::pair<ConstMove, int>&&>);
35 
36 // test constraints
37 // is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
38 // is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
39 static_assert(std::is_constructible_v<std::tuple<int, int>, const std::pair<int, int>&&>);
40 
41 static_assert(!std::is_constructible_v<std::tuple<NoConstructorFromInt, int>, const std::pair<int, int>&&>);
42 
43 static_assert(!std::is_constructible_v<std::tuple<int, NoConstructorFromInt>, const std::pair<int, int>&&>);
44 
45 static_assert(
46     !std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, const std::pair<int, int>&&>);
47 
48 // test: The expression inside explicit is equivalent to:
49 // !is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
50 // !is_convertible_v<decltype(get<1>(FWD(u))), T1>
51 static_assert(std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
52                                     std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
53 
54 static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
55                                      std::tuple<ExplicitConstructibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>>);
56 
57 static_assert(!std::is_convertible_v<const std::pair<ConstMove, ConstMove>&&,
58                                      std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>>);
59 
test()60 constexpr bool test() {
61   // test implicit conversions.
62   {
63     const std::pair<ConstMove, int> p{1, 2};
64     std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<int>> t = std::move(p);
65     assert(std::get<0>(t).v.val == 1);
66     assert(std::get<1>(t).v == 2);
67   }
68 
69   // test explicit conversions.
70   {
71     const std::pair<ConstMove, int> p{1, 2};
72     std::tuple<ExplicitConstructibleFrom<ConstMove>, ExplicitConstructibleFrom<int>> t{std::move(p)};
73     assert(std::get<0>(t).v.val == 1);
74     assert(std::get<1>(t).v == 2);
75   }
76 
77   // non const overload should be called
78   {
79     const std::pair<TracedCopyMove, TracedCopyMove> p;
80     std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = std::move(p);
81     assert(constMoveCtrCalled(std::get<0>(t).v));
82     assert(constMoveCtrCalled(std::get<1>(t)));
83   }
84 
85   return true;
86 }
87 
main(int,char **)88 int main(int, char**) {
89   test();
90   static_assert(test());
91 
92   return 0;
93 }
94