]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp
Vendor import of libc++ trunk r290819:
[FreeBSD/FreeBSD.git] / test / std / utilities / any / any.class / any.modifiers / emplace.pass.cpp
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 // UNSUPPORTED: c++98, c++03, c++11, c++14
11
12 // <any>
13
14 // template <class T, class ...Args> emplace(Args&&...);
15 // template <class T, class U, class ...Args>
16 // void emplace(initializer_list<U>, Args&&...);
17
18 #include <any>
19 #include <cassert>
20
21 #include "any_helpers.h"
22 #include "count_new.hpp"
23 #include "test_macros.h"
24
25 using std::any;
26 using std::any_cast;
27
28 struct Tracked {
29   static int count;
30   Tracked()  {++count;}
31   ~Tracked() { --count; }
32 };
33 int Tracked::count = 0;
34
35 template <class Type>
36 void test_emplace_type() {
37     // constructing from a small type should perform no allocations.
38     DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
39     assert(Type::count == 0);
40     Type::reset();
41     {
42         any a(std::in_place_type<Tracked>);
43         assert(Tracked::count == 1);
44
45         a.emplace<Type>();
46
47         assert(Tracked::count == 0);
48         assert(Type::count == 1);
49         assert(Type::copied == 0);
50         assert(Type::moved == 0);
51         assertContains<Type>(a, 0);
52     }
53     assert(Type::count == 0);
54     Type::reset();
55     {
56         any a(std::in_place_type<Tracked>);
57         assert(Tracked::count == 1);
58
59         a.emplace<Type>(101);
60
61         assert(Tracked::count == 0);
62         assert(Type::count == 1);
63         assert(Type::copied == 0);
64         assert(Type::moved == 0);
65         assertContains<Type>(a, 101);
66     }
67     assert(Type::count == 0);
68     Type::reset();
69     {
70         any a(std::in_place_type<Tracked>);
71         assert(Tracked::count == 1);
72
73         a.emplace<Type>(-1, 42, -1);
74
75         assert(Tracked::count == 0);
76         assert(Type::count == 1);
77         assert(Type::copied == 0);
78         assert(Type::moved == 0);
79         assertContains<Type>(a, 42);
80     }
81     assert(Type::count == 0);
82     Type::reset();
83 }
84
85 template <class Type>
86 void test_emplace_type_tracked() {
87     // constructing from a small type should perform no allocations.
88     DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
89     {
90         any a(std::in_place_type<Tracked>);
91         assert(Tracked::count == 1);
92         a.emplace<Type>();
93         assert(Tracked::count == 0);
94         assertArgsMatch<Type>(a);
95     }
96     {
97         any a(std::in_place_type<Tracked>);
98         assert(Tracked::count == 1);
99         a.emplace<Type>(-1, 42, -1);
100         assert(Tracked::count == 0);
101         assertArgsMatch<Type, int, int, int>(a);
102     }
103     // initializer_list constructor tests
104     {
105         any a(std::in_place_type<Tracked>);
106         assert(Tracked::count == 1);
107         a.emplace<Type>({-1, 42, -1});
108         assert(Tracked::count == 0);
109         assertArgsMatch<Type, std::initializer_list<int>>(a);
110     }
111     {
112         int x = 42;
113         any a(std::in_place_type<Tracked>);
114         assert(Tracked::count == 1);
115         a.emplace<Type>({-1, 42, -1}, x);
116         assert(Tracked::count == 0);
117         assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
118     }
119 }
120
121 #ifndef TEST_HAS_NO_EXCEPTIONS
122
123 struct SmallThrows {
124   SmallThrows(int) { throw 42; }
125   SmallThrows(std::initializer_list<int>, int) { throw 42; }
126 };
127 static_assert(IsSmallObject<SmallThrows>::value, "");
128
129 struct LargeThrows {
130   LargeThrows(int) { throw 42; }
131   LargeThrows(std::initializer_list<int>, int) { throw 42; }
132   int data[sizeof(std::any)];
133 };
134 static_assert(!IsSmallObject<LargeThrows>::value, "");
135
136 template <class Type>
137 void test_emplace_throws()
138 {
139     // any stores small type
140     {
141         std::any a(small{42});
142         assert(small::count == 1);
143         try {
144             a.emplace<Type>(101);
145             assert(false);
146         } catch (int const&) {
147         }
148         assert(small::count == 0);
149     }
150     {
151         std::any a(small{42});
152         assert(small::count == 1);
153         try {
154             a.emplace<Type>({1, 2, 3}, 101);
155             assert(false);
156         } catch (int const&) {
157         }
158         assert(small::count == 0);
159     }
160     // any stores large type
161     {
162         std::any a(large{42});
163         assert(large::count == 1);
164         try {
165             a.emplace<Type>(101);
166             assert(false);
167         } catch (int const&) {
168         }
169         assert(large::count == 0);
170     }
171     {
172         std::any a(large{42});
173         assert(large::count == 1);
174         try {
175             a.emplace<Type>({1, 2, 3}, 101);
176             assert(false);
177         } catch (int const&) {
178         }
179         assert(large::count == 0);
180     }
181 }
182
183 #endif
184
185 template <class T, class ...Args>
186 constexpr auto has_emplace(int)
187     -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }
188
189 template <class ...Args>
190 constexpr bool has_emplace(long) { return false; }
191
192 template <class ...Args>
193 constexpr bool has_emplace() { return has_emplace<Args...>(0); }
194
195
196 template <class T, class IT, class ...Args>
197 constexpr auto has_emplace_init_list(int)
198     -> decltype(std::any{}.emplace<T>(
199         {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()},
200         std::declval<Args>()...), true) { return true; }
201
202 template <class ...Args>
203 constexpr bool has_emplace_init_list(long) { return false; }
204
205 template <class ...Args>
206 constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }
207
208
209 void test_emplace_sfinae_constraints() {
210     {
211         static_assert(has_emplace<int>(), "");
212         static_assert(has_emplace<int, int>(), "");
213         static_assert(!has_emplace<int, int, int>(), "not constructible");
214         static_assert(!has_emplace_init_list<int, int>(), "not constructible from il");
215     }
216     {
217         static_assert(has_emplace<small>(), "");
218         static_assert(has_emplace<large>(), "");
219         static_assert(!has_emplace<small, void*>(), "");
220         static_assert(!has_emplace<large, void*>(), "");
221
222         static_assert(has_emplace_init_list<small, int>(), "");
223         static_assert(has_emplace_init_list<large, int>(), "");
224         static_assert(!has_emplace_init_list<small, void*>(), "");
225         static_assert(!has_emplace_init_list<large, void*>(), "");
226     }
227     {
228         // Test that the emplace SFINAE's away when the
229         // argument is non-copyable
230         struct NoCopy {
231           NoCopy() = default;
232           NoCopy(NoCopy const&) = delete;
233           NoCopy(int) {}
234           NoCopy(std::initializer_list<int>, int, int) {}
235         };
236         static_assert(!has_emplace<NoCopy>(), "");
237         static_assert(!has_emplace<NoCopy, int>(), "");
238         static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), "");
239         static_assert(!has_emplace<NoCopy&>(), "");
240         static_assert(!has_emplace<NoCopy&, int>(), "");
241         static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), "");
242         static_assert(!has_emplace<NoCopy&&>(), "");
243         static_assert(!has_emplace<NoCopy&&, int>(), "");
244         static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), "");
245
246     }
247 }
248
249 int main() {
250     test_emplace_type<small>();
251     test_emplace_type<large>();
252     test_emplace_type<small_throws_on_copy>();
253     test_emplace_type<large_throws_on_copy>();
254     test_emplace_type<throws_on_move>();
255     test_emplace_type_tracked<small_tracked_t>();
256     test_emplace_type_tracked<large_tracked_t>();
257     test_emplace_sfinae_constraints();
258 #ifndef TEST_HAS_NO_EXCEPTIONS
259     test_emplace_throws<SmallThrows>();
260     test_emplace_throws<LargeThrows>();
261 #endif
262 }