1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <tuple>
11 
12 // template <class... Types> class tuple;
13 
14 // template <class Alloc, class... UTypes>
15 //   tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
16 
17 // UNSUPPORTED: c++98, c++03
18 
19 #include <tuple>
20 #include <cassert>
21 
22 #include "MoveOnly.h"
23 #include "allocators.h"
24 #include "../alloc_first.h"
25 #include "../alloc_last.h"
26 
27 struct NoDefault { NoDefault() = delete; };
28 
29 // Make sure the _Up... constructor SFINAEs out when the types that
30 // are not explicitly initialized are not all default constructible.
31 // Otherwise, std::is_constructible would return true but instantiating
32 // the constructor would fail.
test_default_constructible_extension_sfinae()33 void test_default_constructible_extension_sfinae()
34 {
35     {
36         typedef std::tuple<MoveOnly, NoDefault> Tuple;
37 
38         static_assert(!std::is_constructible<
39             Tuple,
40             std::allocator_arg_t, A1<int>, MoveOnly
41         >::value, "");
42 
43         static_assert(std::is_constructible<
44             Tuple,
45             std::allocator_arg_t, A1<int>, MoveOnly, NoDefault
46         >::value, "");
47     }
48     {
49         typedef std::tuple<MoveOnly, MoveOnly, NoDefault> Tuple;
50 
51         static_assert(!std::is_constructible<
52             Tuple,
53             std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly
54         >::value, "");
55 
56         static_assert(std::is_constructible<
57             Tuple,
58             std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly, NoDefault
59         >::value, "");
60     }
61     {
62         // Same idea as above but with a nested tuple
63         typedef std::tuple<MoveOnly, NoDefault> Tuple;
64         typedef std::tuple<MoveOnly, Tuple, MoveOnly, MoveOnly> NestedTuple;
65 
66         static_assert(!std::is_constructible<
67             NestedTuple,
68             std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly, MoveOnly, MoveOnly
69         >::value, "");
70 
71         static_assert(std::is_constructible<
72             NestedTuple,
73             std::allocator_arg_t, A1<int>, MoveOnly, Tuple, MoveOnly, MoveOnly
74         >::value, "");
75     }
76     {
77         typedef std::tuple<MoveOnly, int> Tuple;
78         typedef std::tuple<MoveOnly, Tuple, MoveOnly, MoveOnly> NestedTuple;
79 
80         static_assert(std::is_constructible<
81             NestedTuple,
82             std::allocator_arg_t, A1<int>, MoveOnly, MoveOnly, MoveOnly, MoveOnly
83         >::value, "");
84 
85         static_assert(std::is_constructible<
86             NestedTuple,
87             std::allocator_arg_t, A1<int>, MoveOnly, Tuple, MoveOnly, MoveOnly
88         >::value, "");
89     }
90 }
91 
main()92 int main()
93 {
94     {
95         std::tuple<MoveOnly> t(std::allocator_arg, A1<int>(), MoveOnly(0));
96         assert(std::get<0>(t) == 0);
97     }
98     {
99         std::tuple<MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(),
100                                          MoveOnly(0), MoveOnly(1));
101         assert(std::get<0>(t) == 0);
102         assert(std::get<1>(t) == 1);
103     }
104     {
105         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(),
106                                                    MoveOnly(0),
107                                                    1, 2);
108         assert(std::get<0>(t) == 0);
109         assert(std::get<1>(t) == 1);
110         assert(std::get<2>(t) == 2);
111     }
112     {
113         alloc_first::allocator_constructed = false;
114         alloc_last::allocator_constructed = false;
115         std::tuple<int, alloc_first, alloc_last> t(std::allocator_arg,
116                                                    A1<int>(5), 1, 2, 3);
117         assert(std::get<0>(t) == 1);
118         assert(alloc_first::allocator_constructed);
119         assert(std::get<1>(t) == alloc_first(2));
120         assert(alloc_last::allocator_constructed);
121         assert(std::get<2>(t) == alloc_last(3));
122     }
123     // extensions
124     {
125         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(),
126                                                    0, 1);
127         assert(std::get<0>(t) == 0);
128         assert(std::get<1>(t) == 1);
129         assert(std::get<2>(t) == MoveOnly());
130     }
131     {
132         std::tuple<MoveOnly, MoveOnly, MoveOnly> t(std::allocator_arg, A1<int>(),
133                                                    0);
134         assert(std::get<0>(t) == 0);
135         assert(std::get<1>(t) == MoveOnly());
136         assert(std::get<2>(t) == MoveOnly());
137     }
138     // Check that SFINAE is properly applied with the default reduced arity
139     // constructor extensions.
140     test_default_constructible_extension_sfinae();
141 }
142