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 // UNSUPPORTED: c++98, c++03
10 
11 // <tuple>
12 
13 // template <class... Types> class tuple;
14 
15 // template <class Alloc>
16 //   tuple(allocator_arg_t, const Alloc& a);
17 
18 // NOTE: this constructor does not currently support tags derived from
19 // allocator_arg_t because libc++ has to deduce the parameter as a template
20 // argument. See PR27684 (https://bugs.llvm.org/show_bug.cgi?id=27684)
21 
22 #include <tuple>
23 #include <cassert>
24 
25 #include "DefaultOnly.h"
26 #include "allocators.h"
27 #include "../alloc_first.h"
28 #include "../alloc_last.h"
29 
30 template <class T = void>
31 struct NonDefaultConstructible {
32   constexpr NonDefaultConstructible() {
33       static_assert(!std::is_same<T, T>::value, "Default Ctor instantiated");
34   }
35 
36   explicit constexpr NonDefaultConstructible(int) {}
37 };
38 
39 
40 struct DerivedFromAllocArgT : std::allocator_arg_t {};
41 
42 int main(int, char**)
43 {
44     {
45         std::tuple<> t(std::allocator_arg, A1<int>());
46     }
47     {
48         std::tuple<int> t(std::allocator_arg, A1<int>());
49         assert(std::get<0>(t) == 0);
50     }
51     {
52         std::tuple<DefaultOnly> t(std::allocator_arg, A1<int>());
53         assert(std::get<0>(t) == DefaultOnly());
54     }
55     {
56         assert(!alloc_first::allocator_constructed);
57         std::tuple<alloc_first> t(std::allocator_arg, A1<int>(5));
58         assert(alloc_first::allocator_constructed);
59         assert(std::get<0>(t) == alloc_first());
60     }
61     {
62         assert(!alloc_last::allocator_constructed);
63         std::tuple<alloc_last> t(std::allocator_arg, A1<int>(5));
64         assert(alloc_last::allocator_constructed);
65         assert(std::get<0>(t) == alloc_last());
66     }
67     {
68         alloc_first::allocator_constructed = false;
69         std::tuple<DefaultOnly, alloc_first> t(std::allocator_arg, A1<int>(5));
70         assert(std::get<0>(t) == DefaultOnly());
71         assert(alloc_first::allocator_constructed);
72         assert(std::get<1>(t) == alloc_first());
73     }
74     {
75         alloc_first::allocator_constructed = false;
76         alloc_last::allocator_constructed = false;
77         std::tuple<DefaultOnly, alloc_first, alloc_last> t(std::allocator_arg,
78                                                            A1<int>(5));
79         assert(std::get<0>(t) == DefaultOnly());
80         assert(alloc_first::allocator_constructed);
81         assert(std::get<1>(t) == alloc_first());
82         assert(alloc_last::allocator_constructed);
83         assert(std::get<2>(t) == alloc_last());
84     }
85     {
86         alloc_first::allocator_constructed = false;
87         alloc_last::allocator_constructed = false;
88         std::tuple<DefaultOnly, alloc_first, alloc_last> t(std::allocator_arg,
89                                                            A2<int>(5));
90         assert(std::get<0>(t) == DefaultOnly());
91         assert(!alloc_first::allocator_constructed);
92         assert(std::get<1>(t) == alloc_first());
93         assert(!alloc_last::allocator_constructed);
94         assert(std::get<2>(t) == alloc_last());
95     }
96     {
97         // Test that the uses-allocator default constructor does not evaluate
98         // its SFINAE when it otherwise shouldn't be selected. Do this by
99         // using 'NonDefaultConstructible' which will cause a compile error
100         // if std::is_default_constructible is evaluated on it.
101         using T = NonDefaultConstructible<>;
102         T v(42);
103         std::tuple<T, T> t(v, v);
104         (void)t;
105         std::tuple<T, T> t2(42, 42);
106         (void)t2;
107     }
108 
109   return 0;
110 }
111