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