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