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