]>
Commit | Line | Data |
---|---|---|
52066eae | 1 | // { dg-do run { target c++11 } } |
b8214660 | 2 | |
99dee823 | 3 | // Copyright (C) 2011-2021 Free Software Foundation, Inc. |
b8214660 JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // You should have received a copy of the GNU General Public License along | |
17 | // with this library; see the file COPYING3. If not see | |
18 | // <http://www.gnu.org/licenses/>. | |
19 | ||
20 | // 20.4.2.1 [tuple.cnstr] Allocator-extended constructors | |
21 | ||
22 | #include <memory> | |
23 | #include <tuple> | |
24 | #include <testsuite_hooks.h> | |
25 | ||
26 | struct MyAlloc { }; | |
27 | ||
28 | // type that can't be constructed with an allocator | |
29 | struct CannotUse | |
30 | { | |
31 | CannotUse(int = 0, int = 0) : ok(true) { } | |
32 | ||
33 | bool ok; | |
34 | }; | |
35 | ||
36 | // type that can be constructed with an allocator | |
37 | // but which has uses_allocator == false | |
38 | struct DoesNotUse | |
39 | { | |
40 | typedef MyAlloc allocator_type; | |
41 | ||
42 | DoesNotUse(int = 0) : ok(true) { } | |
43 | DoesNotUse(std::allocator_arg_t, MyAlloc, int = 0) : ok(false) { } | |
44 | DoesNotUse(MyAlloc) : ok(false) { } | |
45 | DoesNotUse(int, MyAlloc) : ok(false) { } | |
46 | ||
47 | DoesNotUse(const DoesNotUse&) : ok(true) { } | |
48 | DoesNotUse(std::allocator_arg_t, MyAlloc, const DoesNotUse&) : ok(false) { } | |
49 | DoesNotUse(const DoesNotUse&, MyAlloc) : ok(false) { } | |
50 | ||
51 | DoesNotUse(DoesNotUse&&) : ok(true) { } | |
52 | DoesNotUse(std::allocator_arg_t, MyAlloc, DoesNotUse&&) : ok(false) { } | |
53 | DoesNotUse(DoesNotUse&&, MyAlloc) : ok(false) { } | |
54 | ||
55 | bool ok; | |
56 | }; | |
57 | ||
58 | namespace std | |
59 | { | |
60 | template<typename A> | |
61 | struct uses_allocator<DoesNotUse, A> : false_type { }; | |
62 | } | |
63 | ||
64 | // type that can be constructed with an allocator as second argument | |
65 | struct UsesWithTag | |
66 | { | |
67 | typedef MyAlloc allocator_type; | |
68 | ||
69 | UsesWithTag(int = 0) : ok(false) { } | |
70 | UsesWithTag(std::allocator_arg_t, MyAlloc, int = 0) : ok(true) { } | |
71 | UsesWithTag(MyAlloc) : ok(false) { } | |
72 | UsesWithTag(int, MyAlloc) : ok(false) { } | |
73 | ||
74 | UsesWithTag(const UsesWithTag&) : ok(false) { } | |
75 | UsesWithTag(std::allocator_arg_t, MyAlloc, const UsesWithTag&) : ok(true) { } | |
76 | UsesWithTag(const UsesWithTag&, MyAlloc) : ok(false) { } | |
77 | ||
78 | UsesWithTag(UsesWithTag&&) : ok(false) { } | |
79 | UsesWithTag(std::allocator_arg_t, MyAlloc, UsesWithTag&&) : ok(true) { } | |
80 | UsesWithTag(UsesWithTag&&, MyAlloc) : ok(false) { } | |
81 | ||
82 | bool ok; | |
83 | }; | |
84 | ||
85 | // type that can be constructed with an allocator as last argument | |
86 | struct UsesWithoutTag | |
87 | { | |
88 | typedef MyAlloc allocator_type; | |
89 | ||
90 | UsesWithoutTag(int = 0) : ok(false) { } | |
91 | UsesWithoutTag(MyAlloc) : ok(true) { } | |
92 | UsesWithoutTag(int, MyAlloc) : ok(true) { } | |
93 | ||
94 | UsesWithoutTag(const UsesWithoutTag&) : ok(false) { } | |
95 | UsesWithoutTag(const UsesWithoutTag&, MyAlloc) : ok(true) { } | |
96 | ||
97 | UsesWithoutTag(UsesWithoutTag&&) : ok(false) { } | |
98 | UsesWithoutTag(UsesWithoutTag&&, MyAlloc) : ok(true) { } | |
99 | ||
100 | bool ok; | |
101 | }; | |
102 | ||
103 | void test01() | |
104 | { | |
b8214660 JW |
105 | using std::allocator_arg; |
106 | using std::tuple; | |
107 | using std::make_tuple; | |
108 | using std::get; | |
109 | ||
110 | typedef CannotUse T1; | |
111 | typedef DoesNotUse T2; | |
112 | typedef UsesWithTag T3; | |
113 | typedef UsesWithoutTag T4; | |
114 | typedef tuple<T1, T2, T3, T4> test_type; | |
115 | ||
116 | MyAlloc a; | |
117 | ||
118 | // default construction | |
119 | test_type t1(allocator_arg, a); | |
120 | VERIFY( get<0>(t1).ok ); | |
121 | VERIFY( get<1>(t1).ok ); | |
122 | VERIFY( get<2>(t1).ok ); | |
123 | VERIFY( get<3>(t1).ok ); | |
124 | ||
125 | // copy construction | |
126 | test_type t2(allocator_arg, a, t1); | |
127 | VERIFY( get<0>(t2).ok ); | |
128 | VERIFY( get<1>(t2).ok ); | |
129 | VERIFY( get<2>(t2).ok ); | |
130 | VERIFY( get<3>(t2).ok ); | |
131 | ||
132 | // move construction | |
133 | test_type t3(allocator_arg, a, std::move(t1)); | |
134 | VERIFY( get<0>(t3).ok ); | |
135 | VERIFY( get<1>(t3).ok ); | |
136 | VERIFY( get<2>(t3).ok ); | |
137 | VERIFY( get<3>(t3).ok ); | |
138 | ||
139 | // construction from int | |
140 | test_type t4(allocator_arg, a, 1, 2, 3, 4); | |
141 | VERIFY( get<0>(t4).ok ); | |
142 | VERIFY( get<1>(t4).ok ); | |
143 | VERIFY( get<2>(t4).ok ); | |
144 | VERIFY( get<3>(t4).ok ); | |
145 | ||
146 | auto ints = make_tuple(1, 2, 3, 4); | |
147 | ||
148 | // construction from lvalue tuple of ints | |
149 | test_type t5(allocator_arg, a, ints); | |
150 | VERIFY( get<0>(t5).ok ); | |
151 | VERIFY( get<1>(t5).ok ); | |
152 | VERIFY( get<2>(t5).ok ); | |
153 | VERIFY( get<3>(t2).ok ); | |
154 | ||
155 | // construction from rvalue tuple of ints | |
156 | test_type t6(allocator_arg, a, std::move(ints)); | |
157 | VERIFY( get<0>(t6).ok ); | |
158 | VERIFY( get<1>(t6).ok ); | |
159 | VERIFY( get<2>(t6).ok ); | |
160 | VERIFY( get<3>(t6).ok ); | |
161 | ||
162 | } | |
163 | ||
dbc6221f VV |
164 | void test02() |
165 | { | |
dbc6221f VV |
166 | using std::allocator_arg; |
167 | using std::tuple; | |
168 | using std::make_tuple; | |
169 | ||
170 | typedef tuple<> test_type; | |
171 | ||
172 | MyAlloc a; | |
173 | ||
174 | // default construction | |
175 | test_type t1(allocator_arg, a); | |
176 | // copy construction | |
177 | test_type t2(allocator_arg, a, t1); | |
178 | // move construction | |
179 | test_type t3(allocator_arg, a, std::move(t1)); | |
180 | // make_tuple | |
181 | test_type empty = make_tuple(); | |
182 | } | |
183 | ||
b7dbc672 JW |
184 | void test03() |
185 | { | |
186 | struct dr2586 | |
187 | { | |
188 | using allocator_type = std::allocator<int>; | |
d355635e | 189 | dr2586() { } |
b7dbc672 | 190 | dr2586(std::allocator_arg_t, allocator_type&&) { } |
d355635e JW |
191 | dr2586(const allocator_type&) : expected(true) { } |
192 | bool expected = false; | |
b7dbc672 JW |
193 | }; |
194 | ||
195 | const dr2586::allocator_type a; | |
196 | std::tuple<dr2586> t{std::allocator_arg, a}; | |
d355635e JW |
197 | VERIFY( std::get<0>(t).expected ); |
198 | } | |
199 | ||
200 | void test04() | |
201 | { | |
202 | struct X { | |
203 | X(std::allocator_arg_t) { } | |
204 | }; | |
205 | ||
206 | // The element types are not default constructible, so the allocator-extended | |
207 | // default constructor should not participate in overload resolution. | |
208 | std::tuple<X, void(&)()> t(std::allocator_arg, *+[]{}); | |
b7dbc672 JW |
209 | } |
210 | ||
b8214660 JW |
211 | int main() |
212 | { | |
213 | test01(); | |
dbc6221f | 214 | test02(); |
b7dbc672 | 215 | test03(); |
d355635e | 216 | test04(); |
b8214660 JW |
217 | return 0; |
218 | } |