Revert "[libc] Use best-fit binary trie to make malloc logarithmic" (#117065)
[llvm-project.git] / libcxx / test / std / utilities / any / any.class / any.modifiers / emplace.pass.cpp
blob3d3ecf9b870ce7acabca4ecd764f1eae9bc53a82
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
11 // <any>
13 // template <class T, class ...Args> T& emplace(Args&&...);
14 // template <class T, class U, class ...Args>
15 // T& emplace(initializer_list<U>, Args&&...);
17 #include <any>
18 #include <cassert>
20 #include "any_helpers.h"
21 #include "count_new.h"
22 #include "test_macros.h"
24 struct Tracked {
25 static int count;
26 Tracked() { ++count; }
27 Tracked(Tracked const&) noexcept { ++count; }
28 Tracked& operator=(Tracked const&) = default;
29 ~Tracked() { --count; }
31 int Tracked::count = 0;
33 template <class Type>
34 void test_emplace_type() {
35 // constructing from a small type should perform no allocations.
36 DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
37 assert(Type::count == 0);
38 Type::reset();
40 std::any a(std::in_place_type<Tracked>);
41 assert(Tracked::count == 1);
43 auto &v = a.emplace<Type>();
44 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
45 assert(&v == std::any_cast<Type>(&a));
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);
53 assert(Type::count == 0);
54 Type::reset();
56 std::any a(std::in_place_type<Tracked>);
57 assert(Tracked::count == 1);
59 auto &v = a.emplace<Type>(101);
60 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
61 assert(&v == std::any_cast<Type>(&a));
63 assert(Tracked::count == 0);
64 assert(Type::count == 1);
65 assert(Type::copied == 0);
66 assert(Type::moved == 0);
67 assertContains<Type>(a, 101);
69 assert(Type::count == 0);
70 Type::reset();
72 std::any a(std::in_place_type<Tracked>);
73 assert(Tracked::count == 1);
75 auto &v = a.emplace<Type>(-1, 42, -1);
76 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
77 assert(&v == std::any_cast<Type>(&a));
79 assert(Tracked::count == 0);
80 assert(Type::count == 1);
81 assert(Type::copied == 0);
82 assert(Type::moved == 0);
83 assertContains<Type>(a, 42);
85 assert(Type::count == 0);
86 Type::reset();
89 template <class Type>
90 void test_emplace_type_tracked() {
91 // constructing from a small type should perform no allocations.
92 DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
94 std::any a(std::in_place_type<Tracked>);
95 assert(Tracked::count == 1);
96 auto &v = a.emplace<Type>();
97 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
98 assert(&v == std::any_cast<Type>(&a));
100 assert(Tracked::count == 0);
101 assertArgsMatch<Type>(a);
104 std::any a(std::in_place_type<Tracked>);
105 assert(Tracked::count == 1);
106 auto &v = a.emplace<Type>(-1, 42, -1);
107 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
108 assert(&v == std::any_cast<Type>(&a));
110 assert(Tracked::count == 0);
111 assertArgsMatch<Type, int, int, int>(a);
113 // initializer_list constructor tests
115 std::any a(std::in_place_type<Tracked>);
116 assert(Tracked::count == 1);
117 auto &v = a.emplace<Type>({-1, 42, -1});
118 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
119 assert(&v == std::any_cast<Type>(&a));
121 assert(Tracked::count == 0);
122 assertArgsMatch<Type, std::initializer_list<int>>(a);
125 int x = 42;
126 std::any a(std::in_place_type<Tracked>);
127 assert(Tracked::count == 1);
128 auto &v = a.emplace<Type>({-1, 42, -1}, x);
129 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
130 assert(&v == std::any_cast<Type>(&a));
132 assert(Tracked::count == 0);
133 assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
137 #ifndef TEST_HAS_NO_EXCEPTIONS
139 struct SmallThrows {
140 SmallThrows(int) { throw 42; }
141 SmallThrows(std::initializer_list<int>, int) { throw 42; }
143 static_assert(IsSmallObject<SmallThrows>::value, "");
145 struct LargeThrows {
146 LargeThrows(int) { throw 42; }
147 LargeThrows(std::initializer_list<int>, int) { throw 42; }
148 int data[sizeof(std::any)];
150 static_assert(!IsSmallObject<LargeThrows>::value, "");
152 template <class Type>
153 void test_emplace_throws()
155 // any stores small type
157 std::any a(small{42});
158 assert(small::count == 1);
159 try {
160 auto &v = a.emplace<Type>(101);
161 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
162 assert(false);
163 } catch (int const&) {
165 assert(small::count == 0);
168 std::any a(small{42});
169 assert(small::count == 1);
170 try {
171 auto &v = a.emplace<Type>({1, 2, 3}, 101);
172 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
173 assert(false);
174 } catch (int const&) {
176 assert(small::count == 0);
178 // any stores large type
180 std::any a(large{42});
181 assert(large::count == 1);
182 try {
183 auto &v = a.emplace<Type>(101);
184 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
185 assert(false);
186 } catch (int const&) {
188 assert(large::count == 0);
191 std::any a(large{42});
192 assert(large::count == 1);
193 try {
194 auto &v = a.emplace<Type>({1, 2, 3}, 101);
195 static_assert( std::is_same_v<Type&, decltype(v)>, "" );
196 assert(false);
197 } catch (int const&) {
199 assert(large::count == 0);
203 #endif
205 template <class T, class ...Args>
206 constexpr auto has_emplace(int)
207 -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }
209 template <class ...Args>
210 constexpr bool has_emplace(long) { return false; }
212 template <class ...Args>
213 constexpr bool has_emplace() { return has_emplace<Args...>(0); }
216 template <class T, class IT, class ...Args>
217 constexpr auto has_emplace_init_list(int)
218 -> decltype(std::any{}.emplace<T>(
219 {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()},
220 std::declval<Args>()...), true) { return true; }
222 template <class ...Args>
223 constexpr bool has_emplace_init_list(long) { return false; }
225 template <class ...Args>
226 constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }
229 void test_emplace_sfinae_constraints() {
231 static_assert(has_emplace<int>(), "");
232 static_assert(has_emplace<int, int>(), "");
233 static_assert(!has_emplace<int, int, int>(), "not constructible");
234 static_assert(!has_emplace_init_list<int, int>(), "not constructible from il");
237 static_assert(has_emplace<small>(), "");
238 static_assert(has_emplace<large>(), "");
239 static_assert(!has_emplace<small, void*>(), "");
240 static_assert(!has_emplace<large, void*>(), "");
242 static_assert(has_emplace_init_list<small, int>(), "");
243 static_assert(has_emplace_init_list<large, int>(), "");
244 static_assert(!has_emplace_init_list<small, void*>(), "");
245 static_assert(!has_emplace_init_list<large, void*>(), "");
248 // Test that the emplace SFINAE's away when the
249 // argument is non-copyable
250 struct NoCopy {
251 NoCopy() = default;
252 NoCopy(NoCopy const&) = delete;
253 NoCopy(int) {}
254 NoCopy(std::initializer_list<int>, int, int) {}
256 static_assert(!has_emplace<NoCopy>(), "");
257 static_assert(!has_emplace<NoCopy, int>(), "");
258 static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), "");
259 static_assert(!has_emplace<NoCopy&>(), "");
260 static_assert(!has_emplace<NoCopy&, int>(), "");
261 static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), "");
262 static_assert(!has_emplace<NoCopy&&>(), "");
263 static_assert(!has_emplace<NoCopy&&, int>(), "");
264 static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), "");
269 int main(int, char**) {
270 test_emplace_type<small>();
271 test_emplace_type<large>();
272 test_emplace_type<small_throws_on_copy>();
273 test_emplace_type<large_throws_on_copy>();
274 test_emplace_type<throws_on_move>();
275 test_emplace_type_tracked<small_tracked_t>();
276 test_emplace_type_tracked<large_tracked_t>();
277 test_emplace_sfinae_constraints();
278 #ifndef TEST_HAS_NO_EXCEPTIONS
279 test_emplace_throws<SmallThrows>();
280 test_emplace_throws<LargeThrows>();
281 #endif
283 return 0;