1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // template <class T, class ...Args> T& emplace(Args&&...);
14 // template <class T, class U, class ...Args>
15 // T& emplace(initializer_list<U>, Args&&...);
20 #include "any_helpers.h"
21 #include "count_new.h"
22 #include "test_macros.h"
26 Tracked() { ++count
; }
27 Tracked(Tracked
const&) noexcept
{ ++count
; }
28 Tracked
& operator=(Tracked
const&) = default;
29 ~Tracked() { --count
; }
31 int Tracked::count
= 0;
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);
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);
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);
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);
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
);
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
140 SmallThrows(int) { throw 42; }
141 SmallThrows(std::initializer_list
<int>, int) { throw 42; }
143 static_assert(IsSmallObject
<SmallThrows
>::value
, "");
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);
160 auto &v
= a
.emplace
<Type
>(101);
161 static_assert( std::is_same_v
<Type
&, decltype(v
)>, "" );
163 } catch (int const&) {
165 assert(small::count
== 0);
168 std::any
a(small
{42});
169 assert(small::count
== 1);
171 auto &v
= a
.emplace
<Type
>({1, 2, 3}, 101);
172 static_assert( std::is_same_v
<Type
&, decltype(v
)>, "" );
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);
183 auto &v
= a
.emplace
<Type
>(101);
184 static_assert( std::is_same_v
<Type
&, decltype(v
)>, "" );
186 } catch (int const&) {
188 assert(large::count
== 0);
191 std::any
a(large
{42});
192 assert(large::count
== 1);
194 auto &v
= a
.emplace
<Type
>({1, 2, 3}, 101);
195 static_assert( std::is_same_v
<Type
&, decltype(v
)>, "" );
197 } catch (int const&) {
199 assert(large::count
== 0);
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
252 NoCopy(NoCopy
const&) = delete;
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
>();