xref: /aosp_15_r20/external/libcxx/test/support/any_helpers.h (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker #ifndef ANY_HELPERS_H
10*58b9f456SAndroid Build Coastguard Worker #define ANY_HELPERS_H
11*58b9f456SAndroid Build Coastguard Worker 
12*58b9f456SAndroid Build Coastguard Worker #include <typeinfo>
13*58b9f456SAndroid Build Coastguard Worker #include <type_traits>
14*58b9f456SAndroid Build Coastguard Worker #include <cassert>
15*58b9f456SAndroid Build Coastguard Worker 
16*58b9f456SAndroid Build Coastguard Worker namespace std { namespace experimental {} }
17*58b9f456SAndroid Build Coastguard Worker 
18*58b9f456SAndroid Build Coastguard Worker #include "test_macros.h"
19*58b9f456SAndroid Build Coastguard Worker #include "type_id.h"
20*58b9f456SAndroid Build Coastguard Worker 
21*58b9f456SAndroid Build Coastguard Worker #if !defined(TEST_HAS_NO_RTTI)
22*58b9f456SAndroid Build Coastguard Worker #define RTTI_ASSERT(X) assert(X)
23*58b9f456SAndroid Build Coastguard Worker #else
24*58b9f456SAndroid Build Coastguard Worker #define RTTI_ASSERT(X)
25*58b9f456SAndroid Build Coastguard Worker #endif
26*58b9f456SAndroid Build Coastguard Worker 
27*58b9f456SAndroid Build Coastguard Worker template <class T>
28*58b9f456SAndroid Build Coastguard Worker   struct IsSmallObject
29*58b9f456SAndroid Build Coastguard Worker     : public std::integral_constant<bool
30*58b9f456SAndroid Build Coastguard Worker         , sizeof(T) <= (sizeof(void*)*3)
31*58b9f456SAndroid Build Coastguard Worker           && std::alignment_of<void*>::value
32*58b9f456SAndroid Build Coastguard Worker              % std::alignment_of<T>::value == 0
33*58b9f456SAndroid Build Coastguard Worker           && std::is_nothrow_move_constructible<T>::value
34*58b9f456SAndroid Build Coastguard Worker         >
35*58b9f456SAndroid Build Coastguard Worker   {};
36*58b9f456SAndroid Build Coastguard Worker 
37*58b9f456SAndroid Build Coastguard Worker template <class T>
containsType(std::any const & a)38*58b9f456SAndroid Build Coastguard Worker bool containsType(std::any const& a) {
39*58b9f456SAndroid Build Coastguard Worker #if !defined(TEST_HAS_NO_RTTI)
40*58b9f456SAndroid Build Coastguard Worker     return a.type() == typeid(T);
41*58b9f456SAndroid Build Coastguard Worker #else
42*58b9f456SAndroid Build Coastguard Worker     return a.has_value() && std::any_cast<T>(&a) != nullptr;
43*58b9f456SAndroid Build Coastguard Worker #endif
44*58b9f456SAndroid Build Coastguard Worker }
45*58b9f456SAndroid Build Coastguard Worker 
46*58b9f456SAndroid Build Coastguard Worker // Return 'true' if 'Type' will be considered a small type by 'any'
47*58b9f456SAndroid Build Coastguard Worker template <class Type>
isSmallType()48*58b9f456SAndroid Build Coastguard Worker bool isSmallType() {
49*58b9f456SAndroid Build Coastguard Worker     return IsSmallObject<Type>::value;
50*58b9f456SAndroid Build Coastguard Worker }
51*58b9f456SAndroid Build Coastguard Worker 
52*58b9f456SAndroid Build Coastguard Worker // Assert that an object is empty. If the object used to contain an object
53*58b9f456SAndroid Build Coastguard Worker // of type 'LastType' check that it can no longer be accessed.
54*58b9f456SAndroid Build Coastguard Worker template <class LastType = int>
assertEmpty(std::any const & a)55*58b9f456SAndroid Build Coastguard Worker void assertEmpty(std::any const& a) {
56*58b9f456SAndroid Build Coastguard Worker     using namespace std;
57*58b9f456SAndroid Build Coastguard Worker     assert(!a.has_value());
58*58b9f456SAndroid Build Coastguard Worker     RTTI_ASSERT(a.type() == typeid(void));
59*58b9f456SAndroid Build Coastguard Worker     assert(any_cast<LastType const>(&a) == nullptr);
60*58b9f456SAndroid Build Coastguard Worker }
61*58b9f456SAndroid Build Coastguard Worker 
62*58b9f456SAndroid Build Coastguard Worker template <class Type>
63*58b9f456SAndroid Build Coastguard Worker constexpr auto has_value_member(int) -> decltype(std::declval<Type&>().value, true)
64*58b9f456SAndroid Build Coastguard Worker { return true; }
has_value_member(long)65*58b9f456SAndroid Build Coastguard Worker template <class> constexpr bool has_value_member(long) { return false; }
66*58b9f456SAndroid Build Coastguard Worker 
67*58b9f456SAndroid Build Coastguard Worker 
68*58b9f456SAndroid Build Coastguard Worker // Assert that an 'any' object stores the specified 'Type' and 'value'.
69*58b9f456SAndroid Build Coastguard Worker template <class Type>
70*58b9f456SAndroid Build Coastguard Worker std::enable_if_t<has_value_member<Type>(0)>
71*58b9f456SAndroid Build Coastguard Worker _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
assertContains(std::any const & a,int value)72*58b9f456SAndroid Build Coastguard Worker assertContains(std::any const& a, int value) {
73*58b9f456SAndroid Build Coastguard Worker     assert(a.has_value());
74*58b9f456SAndroid Build Coastguard Worker     assert(containsType<Type>(a));
75*58b9f456SAndroid Build Coastguard Worker     assert(std::any_cast<Type const &>(a).value == value);
76*58b9f456SAndroid Build Coastguard Worker }
77*58b9f456SAndroid Build Coastguard Worker 
78*58b9f456SAndroid Build Coastguard Worker template <class Type, class Value>
79*58b9f456SAndroid Build Coastguard Worker std::enable_if_t<!has_value_member<Type>(0)>
80*58b9f456SAndroid Build Coastguard Worker _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
assertContains(std::any const & a,Value value)81*58b9f456SAndroid Build Coastguard Worker assertContains(std::any const& a, Value value) {
82*58b9f456SAndroid Build Coastguard Worker     assert(a.has_value());
83*58b9f456SAndroid Build Coastguard Worker     assert(containsType<Type>(a));
84*58b9f456SAndroid Build Coastguard Worker     assert(std::any_cast<Type const &>(a) == value);
85*58b9f456SAndroid Build Coastguard Worker }
86*58b9f456SAndroid Build Coastguard Worker 
87*58b9f456SAndroid Build Coastguard Worker 
88*58b9f456SAndroid Build Coastguard Worker // Modify the value of a "test type" stored within an any to the specified
89*58b9f456SAndroid Build Coastguard Worker // 'value'.
90*58b9f456SAndroid Build Coastguard Worker template <class Type>
91*58b9f456SAndroid Build Coastguard Worker _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
modifyValue(std::any & a,int value)92*58b9f456SAndroid Build Coastguard Worker void modifyValue(std::any& a, int value) {
93*58b9f456SAndroid Build Coastguard Worker     using namespace std;
94*58b9f456SAndroid Build Coastguard Worker     using namespace std::experimental;
95*58b9f456SAndroid Build Coastguard Worker     assert(a.has_value());
96*58b9f456SAndroid Build Coastguard Worker     assert(containsType<Type>(a));
97*58b9f456SAndroid Build Coastguard Worker     any_cast<Type&>(a).value = value;
98*58b9f456SAndroid Build Coastguard Worker }
99*58b9f456SAndroid Build Coastguard Worker 
100*58b9f456SAndroid Build Coastguard Worker // A test type that will trigger the small object optimization within 'any'.
101*58b9f456SAndroid Build Coastguard Worker template <int Dummy = 0>
102*58b9f456SAndroid Build Coastguard Worker struct small_type
103*58b9f456SAndroid Build Coastguard Worker {
104*58b9f456SAndroid Build Coastguard Worker     static int count;
105*58b9f456SAndroid Build Coastguard Worker     static int copied;
106*58b9f456SAndroid Build Coastguard Worker     static int moved;
107*58b9f456SAndroid Build Coastguard Worker     static int const_copied;
108*58b9f456SAndroid Build Coastguard Worker     static int non_const_copied;
109*58b9f456SAndroid Build Coastguard Worker 
resetsmall_type110*58b9f456SAndroid Build Coastguard Worker     static void reset() {
111*58b9f456SAndroid Build Coastguard Worker         small_type::copied = 0;
112*58b9f456SAndroid Build Coastguard Worker         small_type::moved = 0;
113*58b9f456SAndroid Build Coastguard Worker         small_type::const_copied = 0;
114*58b9f456SAndroid Build Coastguard Worker         small_type::non_const_copied = 0;
115*58b9f456SAndroid Build Coastguard Worker     }
116*58b9f456SAndroid Build Coastguard Worker 
117*58b9f456SAndroid Build Coastguard Worker     int value;
118*58b9f456SAndroid Build Coastguard Worker 
valuesmall_type119*58b9f456SAndroid Build Coastguard Worker     explicit small_type(int val = 0) : value(val) {
120*58b9f456SAndroid Build Coastguard Worker         ++count;
121*58b9f456SAndroid Build Coastguard Worker     }
small_typesmall_type122*58b9f456SAndroid Build Coastguard Worker     explicit small_type(int, int val, int) : value(val) {
123*58b9f456SAndroid Build Coastguard Worker         ++count;
124*58b9f456SAndroid Build Coastguard Worker     }
small_typesmall_type125*58b9f456SAndroid Build Coastguard Worker     small_type(std::initializer_list<int> il) : value(*il.begin()) {
126*58b9f456SAndroid Build Coastguard Worker         ++count;
127*58b9f456SAndroid Build Coastguard Worker     }
128*58b9f456SAndroid Build Coastguard Worker 
small_typesmall_type129*58b9f456SAndroid Build Coastguard Worker     small_type(small_type const & other) noexcept {
130*58b9f456SAndroid Build Coastguard Worker         value = other.value;
131*58b9f456SAndroid Build Coastguard Worker         ++count;
132*58b9f456SAndroid Build Coastguard Worker         ++copied;
133*58b9f456SAndroid Build Coastguard Worker         ++const_copied;
134*58b9f456SAndroid Build Coastguard Worker     }
135*58b9f456SAndroid Build Coastguard Worker 
small_typesmall_type136*58b9f456SAndroid Build Coastguard Worker     small_type(small_type& other) noexcept {
137*58b9f456SAndroid Build Coastguard Worker         value = other.value;
138*58b9f456SAndroid Build Coastguard Worker         ++count;
139*58b9f456SAndroid Build Coastguard Worker         ++copied;
140*58b9f456SAndroid Build Coastguard Worker         ++non_const_copied;
141*58b9f456SAndroid Build Coastguard Worker     }
142*58b9f456SAndroid Build Coastguard Worker 
small_typesmall_type143*58b9f456SAndroid Build Coastguard Worker     small_type(small_type && other) noexcept {
144*58b9f456SAndroid Build Coastguard Worker         value = other.value;
145*58b9f456SAndroid Build Coastguard Worker         other.value = 0;
146*58b9f456SAndroid Build Coastguard Worker         ++count;
147*58b9f456SAndroid Build Coastguard Worker         ++moved;
148*58b9f456SAndroid Build Coastguard Worker     }
149*58b9f456SAndroid Build Coastguard Worker 
~small_typesmall_type150*58b9f456SAndroid Build Coastguard Worker     ~small_type() {
151*58b9f456SAndroid Build Coastguard Worker         value = -1;
152*58b9f456SAndroid Build Coastguard Worker         --count;
153*58b9f456SAndroid Build Coastguard Worker     }
154*58b9f456SAndroid Build Coastguard Worker 
155*58b9f456SAndroid Build Coastguard Worker private:
156*58b9f456SAndroid Build Coastguard Worker     small_type& operator=(small_type const&) = delete;
157*58b9f456SAndroid Build Coastguard Worker     small_type& operator=(small_type&&) = delete;
158*58b9f456SAndroid Build Coastguard Worker };
159*58b9f456SAndroid Build Coastguard Worker 
160*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
161*58b9f456SAndroid Build Coastguard Worker int small_type<Dummy>::count = 0;
162*58b9f456SAndroid Build Coastguard Worker 
163*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
164*58b9f456SAndroid Build Coastguard Worker int small_type<Dummy>::copied = 0;
165*58b9f456SAndroid Build Coastguard Worker 
166*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
167*58b9f456SAndroid Build Coastguard Worker int small_type<Dummy>::moved = 0;
168*58b9f456SAndroid Build Coastguard Worker 
169*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
170*58b9f456SAndroid Build Coastguard Worker int small_type<Dummy>::const_copied = 0;
171*58b9f456SAndroid Build Coastguard Worker 
172*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
173*58b9f456SAndroid Build Coastguard Worker int small_type<Dummy>::non_const_copied = 0;
174*58b9f456SAndroid Build Coastguard Worker 
175*58b9f456SAndroid Build Coastguard Worker typedef small_type<> small;
176*58b9f456SAndroid Build Coastguard Worker typedef small_type<1> small1;
177*58b9f456SAndroid Build Coastguard Worker typedef small_type<2> small2;
178*58b9f456SAndroid Build Coastguard Worker 
179*58b9f456SAndroid Build Coastguard Worker 
180*58b9f456SAndroid Build Coastguard Worker // A test type that will NOT trigger the small object optimization in any.
181*58b9f456SAndroid Build Coastguard Worker template <int Dummy = 0>
182*58b9f456SAndroid Build Coastguard Worker struct large_type
183*58b9f456SAndroid Build Coastguard Worker {
184*58b9f456SAndroid Build Coastguard Worker     static int count;
185*58b9f456SAndroid Build Coastguard Worker     static int copied;
186*58b9f456SAndroid Build Coastguard Worker     static int moved;
187*58b9f456SAndroid Build Coastguard Worker     static int const_copied;
188*58b9f456SAndroid Build Coastguard Worker     static int non_const_copied;
189*58b9f456SAndroid Build Coastguard Worker 
resetlarge_type190*58b9f456SAndroid Build Coastguard Worker     static void reset() {
191*58b9f456SAndroid Build Coastguard Worker         large_type::copied = 0;
192*58b9f456SAndroid Build Coastguard Worker         large_type::moved  = 0;
193*58b9f456SAndroid Build Coastguard Worker         large_type::const_copied = 0;
194*58b9f456SAndroid Build Coastguard Worker         large_type::non_const_copied = 0;
195*58b9f456SAndroid Build Coastguard Worker     }
196*58b9f456SAndroid Build Coastguard Worker 
197*58b9f456SAndroid Build Coastguard Worker     int value;
198*58b9f456SAndroid Build Coastguard Worker 
valuelarge_type199*58b9f456SAndroid Build Coastguard Worker     large_type(int val = 0) : value(val) {
200*58b9f456SAndroid Build Coastguard Worker         ++count;
201*58b9f456SAndroid Build Coastguard Worker         data[0] = 0;
202*58b9f456SAndroid Build Coastguard Worker     }
large_typelarge_type203*58b9f456SAndroid Build Coastguard Worker     large_type(int, int val, int) : value(val) {
204*58b9f456SAndroid Build Coastguard Worker         ++count;
205*58b9f456SAndroid Build Coastguard Worker         data[0] = 0;
206*58b9f456SAndroid Build Coastguard Worker     }
large_typelarge_type207*58b9f456SAndroid Build Coastguard Worker     large_type(std::initializer_list<int> il) : value(*il.begin()) {
208*58b9f456SAndroid Build Coastguard Worker         ++count;
209*58b9f456SAndroid Build Coastguard Worker     }
large_typelarge_type210*58b9f456SAndroid Build Coastguard Worker     large_type(large_type const & other) {
211*58b9f456SAndroid Build Coastguard Worker         value = other.value;
212*58b9f456SAndroid Build Coastguard Worker         ++count;
213*58b9f456SAndroid Build Coastguard Worker         ++copied;
214*58b9f456SAndroid Build Coastguard Worker         ++const_copied;
215*58b9f456SAndroid Build Coastguard Worker     }
216*58b9f456SAndroid Build Coastguard Worker 
large_typelarge_type217*58b9f456SAndroid Build Coastguard Worker     large_type(large_type & other) {
218*58b9f456SAndroid Build Coastguard Worker         value = other.value;
219*58b9f456SAndroid Build Coastguard Worker         ++count;
220*58b9f456SAndroid Build Coastguard Worker         ++copied;
221*58b9f456SAndroid Build Coastguard Worker         ++non_const_copied;
222*58b9f456SAndroid Build Coastguard Worker     }
223*58b9f456SAndroid Build Coastguard Worker 
large_typelarge_type224*58b9f456SAndroid Build Coastguard Worker     large_type(large_type && other) {
225*58b9f456SAndroid Build Coastguard Worker         value = other.value;
226*58b9f456SAndroid Build Coastguard Worker         other.value = 0;
227*58b9f456SAndroid Build Coastguard Worker         ++count;
228*58b9f456SAndroid Build Coastguard Worker         ++moved;
229*58b9f456SAndroid Build Coastguard Worker     }
230*58b9f456SAndroid Build Coastguard Worker 
~large_typelarge_type231*58b9f456SAndroid Build Coastguard Worker     ~large_type()  {
232*58b9f456SAndroid Build Coastguard Worker         value = 0;
233*58b9f456SAndroid Build Coastguard Worker         --count;
234*58b9f456SAndroid Build Coastguard Worker     }
235*58b9f456SAndroid Build Coastguard Worker 
236*58b9f456SAndroid Build Coastguard Worker private:
237*58b9f456SAndroid Build Coastguard Worker     large_type& operator=(large_type const&) = delete;
238*58b9f456SAndroid Build Coastguard Worker     large_type& operator=(large_type &&) = delete;
239*58b9f456SAndroid Build Coastguard Worker     int data[10];
240*58b9f456SAndroid Build Coastguard Worker };
241*58b9f456SAndroid Build Coastguard Worker 
242*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
243*58b9f456SAndroid Build Coastguard Worker int large_type<Dummy>::count = 0;
244*58b9f456SAndroid Build Coastguard Worker 
245*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
246*58b9f456SAndroid Build Coastguard Worker int large_type<Dummy>::copied = 0;
247*58b9f456SAndroid Build Coastguard Worker 
248*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
249*58b9f456SAndroid Build Coastguard Worker int large_type<Dummy>::moved = 0;
250*58b9f456SAndroid Build Coastguard Worker 
251*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
252*58b9f456SAndroid Build Coastguard Worker int large_type<Dummy>::const_copied = 0;
253*58b9f456SAndroid Build Coastguard Worker 
254*58b9f456SAndroid Build Coastguard Worker template <int Dummy>
255*58b9f456SAndroid Build Coastguard Worker int large_type<Dummy>::non_const_copied = 0;
256*58b9f456SAndroid Build Coastguard Worker 
257*58b9f456SAndroid Build Coastguard Worker typedef large_type<> large;
258*58b9f456SAndroid Build Coastguard Worker typedef large_type<1> large1;
259*58b9f456SAndroid Build Coastguard Worker typedef large_type<2> large2;
260*58b9f456SAndroid Build Coastguard Worker 
261*58b9f456SAndroid Build Coastguard Worker // The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy'
262*58b9f456SAndroid Build Coastguard Worker // and 'throws_on_move'.
263*58b9f456SAndroid Build Coastguard Worker struct my_any_exception {};
264*58b9f456SAndroid Build Coastguard Worker 
throwMyAnyExpression()265*58b9f456SAndroid Build Coastguard Worker void throwMyAnyExpression() {
266*58b9f456SAndroid Build Coastguard Worker #if !defined(TEST_HAS_NO_EXCEPTIONS)
267*58b9f456SAndroid Build Coastguard Worker         throw my_any_exception();
268*58b9f456SAndroid Build Coastguard Worker #else
269*58b9f456SAndroid Build Coastguard Worker         assert(false && "Exceptions are disabled");
270*58b9f456SAndroid Build Coastguard Worker #endif
271*58b9f456SAndroid Build Coastguard Worker }
272*58b9f456SAndroid Build Coastguard Worker 
273*58b9f456SAndroid Build Coastguard Worker // A test type that will trigger the small object optimization within 'any'.
274*58b9f456SAndroid Build Coastguard Worker // this type throws if it is copied.
275*58b9f456SAndroid Build Coastguard Worker struct small_throws_on_copy
276*58b9f456SAndroid Build Coastguard Worker {
277*58b9f456SAndroid Build Coastguard Worker     static int count;
278*58b9f456SAndroid Build Coastguard Worker     static int copied;
279*58b9f456SAndroid Build Coastguard Worker     static int moved;
resetsmall_throws_on_copy280*58b9f456SAndroid Build Coastguard Worker     static void reset() { count = copied = moved = 0; }
281*58b9f456SAndroid Build Coastguard Worker     int value;
282*58b9f456SAndroid Build Coastguard Worker 
valuesmall_throws_on_copy283*58b9f456SAndroid Build Coastguard Worker     explicit small_throws_on_copy(int val = 0) : value(val) {
284*58b9f456SAndroid Build Coastguard Worker         ++count;
285*58b9f456SAndroid Build Coastguard Worker     }
small_throws_on_copysmall_throws_on_copy286*58b9f456SAndroid Build Coastguard Worker     explicit small_throws_on_copy(int, int val, int) : value(val) {
287*58b9f456SAndroid Build Coastguard Worker         ++count;
288*58b9f456SAndroid Build Coastguard Worker     }
small_throws_on_copysmall_throws_on_copy289*58b9f456SAndroid Build Coastguard Worker     small_throws_on_copy(small_throws_on_copy const &) {
290*58b9f456SAndroid Build Coastguard Worker         throwMyAnyExpression();
291*58b9f456SAndroid Build Coastguard Worker     }
292*58b9f456SAndroid Build Coastguard Worker 
throwsmall_throws_on_copy293*58b9f456SAndroid Build Coastguard Worker     small_throws_on_copy(small_throws_on_copy && other) throw() {
294*58b9f456SAndroid Build Coastguard Worker         value = other.value;
295*58b9f456SAndroid Build Coastguard Worker         ++count; ++moved;
296*58b9f456SAndroid Build Coastguard Worker     }
297*58b9f456SAndroid Build Coastguard Worker 
~small_throws_on_copysmall_throws_on_copy298*58b9f456SAndroid Build Coastguard Worker     ~small_throws_on_copy() {
299*58b9f456SAndroid Build Coastguard Worker         --count;
300*58b9f456SAndroid Build Coastguard Worker     }
301*58b9f456SAndroid Build Coastguard Worker private:
302*58b9f456SAndroid Build Coastguard Worker     small_throws_on_copy& operator=(small_throws_on_copy const&) = delete;
303*58b9f456SAndroid Build Coastguard Worker     small_throws_on_copy& operator=(small_throws_on_copy &&) = delete;
304*58b9f456SAndroid Build Coastguard Worker };
305*58b9f456SAndroid Build Coastguard Worker 
306*58b9f456SAndroid Build Coastguard Worker int small_throws_on_copy::count = 0;
307*58b9f456SAndroid Build Coastguard Worker int small_throws_on_copy::copied = 0;
308*58b9f456SAndroid Build Coastguard Worker int small_throws_on_copy::moved = 0;
309*58b9f456SAndroid Build Coastguard Worker 
310*58b9f456SAndroid Build Coastguard Worker 
311*58b9f456SAndroid Build Coastguard Worker // A test type that will NOT trigger the small object optimization within 'any'.
312*58b9f456SAndroid Build Coastguard Worker // this type throws if it is copied.
313*58b9f456SAndroid Build Coastguard Worker struct large_throws_on_copy
314*58b9f456SAndroid Build Coastguard Worker {
315*58b9f456SAndroid Build Coastguard Worker     static int count;
316*58b9f456SAndroid Build Coastguard Worker     static int copied;
317*58b9f456SAndroid Build Coastguard Worker     static int moved;
resetlarge_throws_on_copy318*58b9f456SAndroid Build Coastguard Worker     static void reset() { count = copied = moved = 0; }
319*58b9f456SAndroid Build Coastguard Worker     int value = 0;
320*58b9f456SAndroid Build Coastguard Worker 
valuelarge_throws_on_copy321*58b9f456SAndroid Build Coastguard Worker     explicit large_throws_on_copy(int val = 0) : value(val) {
322*58b9f456SAndroid Build Coastguard Worker         data[0] = 0;
323*58b9f456SAndroid Build Coastguard Worker         ++count;
324*58b9f456SAndroid Build Coastguard Worker     }
large_throws_on_copylarge_throws_on_copy325*58b9f456SAndroid Build Coastguard Worker     explicit large_throws_on_copy(int, int val, int) : value(val) {
326*58b9f456SAndroid Build Coastguard Worker         data[0] = 0;
327*58b9f456SAndroid Build Coastguard Worker         ++count;
328*58b9f456SAndroid Build Coastguard Worker     }
large_throws_on_copylarge_throws_on_copy329*58b9f456SAndroid Build Coastguard Worker     large_throws_on_copy(large_throws_on_copy const &) {
330*58b9f456SAndroid Build Coastguard Worker          throwMyAnyExpression();
331*58b9f456SAndroid Build Coastguard Worker     }
332*58b9f456SAndroid Build Coastguard Worker 
throwlarge_throws_on_copy333*58b9f456SAndroid Build Coastguard Worker     large_throws_on_copy(large_throws_on_copy && other) throw() {
334*58b9f456SAndroid Build Coastguard Worker         value = other.value;
335*58b9f456SAndroid Build Coastguard Worker         ++count; ++moved;
336*58b9f456SAndroid Build Coastguard Worker     }
337*58b9f456SAndroid Build Coastguard Worker 
~large_throws_on_copylarge_throws_on_copy338*58b9f456SAndroid Build Coastguard Worker     ~large_throws_on_copy() {
339*58b9f456SAndroid Build Coastguard Worker         --count;
340*58b9f456SAndroid Build Coastguard Worker     }
341*58b9f456SAndroid Build Coastguard Worker 
342*58b9f456SAndroid Build Coastguard Worker private:
343*58b9f456SAndroid Build Coastguard Worker     large_throws_on_copy& operator=(large_throws_on_copy const&) = delete;
344*58b9f456SAndroid Build Coastguard Worker     large_throws_on_copy& operator=(large_throws_on_copy &&) = delete;
345*58b9f456SAndroid Build Coastguard Worker     int data[10];
346*58b9f456SAndroid Build Coastguard Worker };
347*58b9f456SAndroid Build Coastguard Worker 
348*58b9f456SAndroid Build Coastguard Worker int large_throws_on_copy::count = 0;
349*58b9f456SAndroid Build Coastguard Worker int large_throws_on_copy::copied = 0;
350*58b9f456SAndroid Build Coastguard Worker int large_throws_on_copy::moved = 0;
351*58b9f456SAndroid Build Coastguard Worker 
352*58b9f456SAndroid Build Coastguard Worker // A test type that throws when it is moved. This object will NOT trigger
353*58b9f456SAndroid Build Coastguard Worker // the small object optimization in 'any'.
354*58b9f456SAndroid Build Coastguard Worker struct throws_on_move
355*58b9f456SAndroid Build Coastguard Worker {
356*58b9f456SAndroid Build Coastguard Worker     static int count;
357*58b9f456SAndroid Build Coastguard Worker     static int copied;
358*58b9f456SAndroid Build Coastguard Worker     static int moved;
resetthrows_on_move359*58b9f456SAndroid Build Coastguard Worker     static void reset() { count = copied = moved = 0; }
360*58b9f456SAndroid Build Coastguard Worker     int value;
361*58b9f456SAndroid Build Coastguard Worker 
valuethrows_on_move362*58b9f456SAndroid Build Coastguard Worker     explicit throws_on_move(int val = 0) : value(val) { ++count; }
throws_on_movethrows_on_move363*58b9f456SAndroid Build Coastguard Worker     explicit throws_on_move(int, int val, int) : value(val) { ++count; }
throws_on_movethrows_on_move364*58b9f456SAndroid Build Coastguard Worker     throws_on_move(throws_on_move const & other) {
365*58b9f456SAndroid Build Coastguard Worker         value = other.value;
366*58b9f456SAndroid Build Coastguard Worker         ++count; ++copied;
367*58b9f456SAndroid Build Coastguard Worker     }
368*58b9f456SAndroid Build Coastguard Worker 
throws_on_movethrows_on_move369*58b9f456SAndroid Build Coastguard Worker     throws_on_move(throws_on_move &&) {
370*58b9f456SAndroid Build Coastguard Worker         throwMyAnyExpression();
371*58b9f456SAndroid Build Coastguard Worker     }
372*58b9f456SAndroid Build Coastguard Worker 
~throws_on_movethrows_on_move373*58b9f456SAndroid Build Coastguard Worker     ~throws_on_move() {
374*58b9f456SAndroid Build Coastguard Worker         --count;
375*58b9f456SAndroid Build Coastguard Worker     }
376*58b9f456SAndroid Build Coastguard Worker private:
377*58b9f456SAndroid Build Coastguard Worker     throws_on_move& operator=(throws_on_move const&) = delete;
378*58b9f456SAndroid Build Coastguard Worker     throws_on_move& operator=(throws_on_move &&) = delete;
379*58b9f456SAndroid Build Coastguard Worker };
380*58b9f456SAndroid Build Coastguard Worker 
381*58b9f456SAndroid Build Coastguard Worker int throws_on_move::count = 0;
382*58b9f456SAndroid Build Coastguard Worker int throws_on_move::copied = 0;
383*58b9f456SAndroid Build Coastguard Worker int throws_on_move::moved = 0;
384*58b9f456SAndroid Build Coastguard Worker 
385*58b9f456SAndroid Build Coastguard Worker struct small_tracked_t {
small_tracked_tsmall_tracked_t386*58b9f456SAndroid Build Coastguard Worker   small_tracked_t()
387*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<>()) {}
small_tracked_tsmall_tracked_t388*58b9f456SAndroid Build Coastguard Worker   small_tracked_t(small_tracked_t const&) noexcept
389*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<small_tracked_t const&>()) {}
small_tracked_tsmall_tracked_t390*58b9f456SAndroid Build Coastguard Worker   small_tracked_t(small_tracked_t &&) noexcept
391*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<small_tracked_t &&>()) {}
392*58b9f456SAndroid Build Coastguard Worker   template <class ...Args>
small_tracked_tsmall_tracked_t393*58b9f456SAndroid Build Coastguard Worker   explicit small_tracked_t(Args&&...)
394*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<Args...>()) {}
395*58b9f456SAndroid Build Coastguard Worker   template <class ...Args>
small_tracked_tsmall_tracked_t396*58b9f456SAndroid Build Coastguard Worker   explicit small_tracked_t(std::initializer_list<int>, Args&&...)
397*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}
398*58b9f456SAndroid Build Coastguard Worker 
399*58b9f456SAndroid Build Coastguard Worker   TypeID const* arg_types;
400*58b9f456SAndroid Build Coastguard Worker };
401*58b9f456SAndroid Build Coastguard Worker static_assert(IsSmallObject<small_tracked_t>::value, "must be small");
402*58b9f456SAndroid Build Coastguard Worker 
403*58b9f456SAndroid Build Coastguard Worker struct large_tracked_t {
large_tracked_tlarge_tracked_t404*58b9f456SAndroid Build Coastguard Worker   large_tracked_t()
405*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<>()) { dummy[0] = 42; }
large_tracked_tlarge_tracked_t406*58b9f456SAndroid Build Coastguard Worker   large_tracked_t(large_tracked_t const&) noexcept
407*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<large_tracked_t const&>()) {}
large_tracked_tlarge_tracked_t408*58b9f456SAndroid Build Coastguard Worker   large_tracked_t(large_tracked_t &&) noexcept
409*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<large_tracked_t &&>()) {}
410*58b9f456SAndroid Build Coastguard Worker   template <class ...Args>
large_tracked_tlarge_tracked_t411*58b9f456SAndroid Build Coastguard Worker   explicit large_tracked_t(Args&&...)
412*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<Args...>()) {}
413*58b9f456SAndroid Build Coastguard Worker   template <class ...Args>
large_tracked_tlarge_tracked_t414*58b9f456SAndroid Build Coastguard Worker   explicit large_tracked_t(std::initializer_list<int>, Args&&...)
415*58b9f456SAndroid Build Coastguard Worker       : arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}
416*58b9f456SAndroid Build Coastguard Worker 
417*58b9f456SAndroid Build Coastguard Worker   TypeID const* arg_types;
418*58b9f456SAndroid Build Coastguard Worker   int dummy[10];
419*58b9f456SAndroid Build Coastguard Worker };
420*58b9f456SAndroid Build Coastguard Worker 
421*58b9f456SAndroid Build Coastguard Worker static_assert(!IsSmallObject<large_tracked_t>::value, "must be small");
422*58b9f456SAndroid Build Coastguard Worker 
423*58b9f456SAndroid Build Coastguard Worker 
424*58b9f456SAndroid Build Coastguard Worker template <class Type, class ...Args>
assertArgsMatch(std::any const & a)425*58b9f456SAndroid Build Coastguard Worker void assertArgsMatch(std::any const& a) {
426*58b9f456SAndroid Build Coastguard Worker     using namespace std;
427*58b9f456SAndroid Build Coastguard Worker     using namespace std::experimental;
428*58b9f456SAndroid Build Coastguard Worker     assert(a.has_value());
429*58b9f456SAndroid Build Coastguard Worker     assert(containsType<Type>(a));
430*58b9f456SAndroid Build Coastguard Worker     assert(any_cast<Type const &>(a).arg_types == &makeArgumentID<Args...>());
431*58b9f456SAndroid Build Coastguard Worker };
432*58b9f456SAndroid Build Coastguard Worker 
433*58b9f456SAndroid Build Coastguard Worker 
434*58b9f456SAndroid Build Coastguard Worker #endif
435