1 //===----------------------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
14 // template <class T, class ...Args> emplace(Args&&...);
15 // template <class T, class U, class ...Args>
16 // void emplace(initializer_list<U>, Args&&...);
21 #include "any_helpers.h"
22 #include "count_new.hpp"
23 #include "test_macros.h"
31 ~Tracked() { --count; }
33 int Tracked::count = 0;
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);
42 any a(std::in_place_type<Tracked>);
43 assert(Tracked::count == 1);
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 any a(std::in_place_type<Tracked>);
57 assert(Tracked::count == 1);
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);
67 assert(Type::count == 0);
70 any a(std::in_place_type<Tracked>);
71 assert(Tracked::count == 1);
73 a.emplace<Type>(-1, 42, -1);
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);
81 assert(Type::count == 0);
86 void test_emplace_type_tracked() {
87 // constructing from a small type should perform no allocations.
88 DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
90 any a(std::in_place_type<Tracked>);
91 assert(Tracked::count == 1);
93 assert(Tracked::count == 0);
94 assertArgsMatch<Type>(a);
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);
103 // initializer_list constructor tests
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);
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);
121 #ifndef TEST_HAS_NO_EXCEPTIONS
124 SmallThrows(int) { throw 42; }
125 SmallThrows(std::initializer_list<int>, int) { throw 42; }
127 static_assert(IsSmallObject<SmallThrows>::value, "");
130 LargeThrows(int) { throw 42; }
131 LargeThrows(std::initializer_list<int>, int) { throw 42; }
132 int data[sizeof(std::any)];
134 static_assert(!IsSmallObject<LargeThrows>::value, "");
136 template <class Type>
137 void test_emplace_throws()
139 // any stores small type
141 std::any a(small{42});
142 assert(small::count == 1);
144 a.emplace<Type>(101);
146 } catch (int const&) {
148 assert(small::count == 0);
151 std::any a(small{42});
152 assert(small::count == 1);
154 a.emplace<Type>({1, 2, 3}, 101);
156 } catch (int const&) {
158 assert(small::count == 0);
160 // any stores large type
162 std::any a(large{42});
163 assert(large::count == 1);
165 a.emplace<Type>(101);
167 } catch (int const&) {
169 assert(large::count == 0);
172 std::any a(large{42});
173 assert(large::count == 1);
175 a.emplace<Type>({1, 2, 3}, 101);
177 } catch (int const&) {
179 assert(large::count == 0);
185 template <class T, class ...Args>
186 constexpr auto has_emplace(int)
187 -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }
189 template <class ...Args>
190 constexpr bool has_emplace(long) { return false; }
192 template <class ...Args>
193 constexpr bool has_emplace() { return has_emplace<Args...>(0); }
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; }
202 template <class ...Args>
203 constexpr bool has_emplace_init_list(long) { return false; }
205 template <class ...Args>
206 constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }
209 void test_emplace_sfinae_constraints() {
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");
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*>(), "");
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*>(), "");
228 // Test that the emplace SFINAE's away when the
229 // argument is non-copyable
232 NoCopy(NoCopy const&) = delete;
234 NoCopy(std::initializer_list<int>, int, int) {}
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>(), "");
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>();