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 // <any>
13 
14 // template <class ValueType>
15 // ValueType const any_cast(any const&);
16 //
17 // template <class ValueType>
18 // ValueType any_cast(any &);
19 //
20 // template <class ValueType>
21 // ValueType any_cast(any &&);
22 
23 #include <any>
24 #include <type_traits>
25 #include <cassert>
26 
27 #include "any_helpers.h"
28 #include "count_new.hpp"
29 #include "test_macros.h"
30 
31 using std::any;
32 using std::any_cast;
33 using std::bad_any_cast;
34 
35 
36 // Test that the operators are NOT marked noexcept.
test_cast_is_not_noexcept()37 void test_cast_is_not_noexcept() {
38     any a;
39     static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), "");
40     static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), "");
41     static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), "");
42 }
43 
44 // Test that the return type of any_cast is correct.
test_cast_return_type()45 void test_cast_return_type() {
46     any a;
47     static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, "");
48     static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, "");
49     static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, "");
50     static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, "");
51 
52     static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, "");
53     static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, "");
54 
55     static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, "");
56     static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, "");
57     static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, "");
58     static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, "");
59 
60     static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, "");
61     static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, "");
62 
63     any const& ca = a;
64     static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, "");
65     static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, "");
66     static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, "");
67 
68     static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, "");
69 }
70 
71 template <class Type, class ConstT = Type>
checkThrows(any & a)72 void checkThrows(any& a)
73 {
74 #if !defined(TEST_HAS_NO_EXCEPTIONS)
75     try {
76         any_cast<Type>(a);
77         assert(false);
78     } catch (bad_any_cast const &) {
79             // do nothing
80     } catch (...) {
81         assert(false);
82     }
83 
84     try {
85         any_cast<ConstT>(static_cast<any const&>(a));
86         assert(false);
87     } catch (bad_any_cast const &) {
88             // do nothing
89     } catch (...) {
90         assert(false);
91     }
92 
93     try {
94         using RefType = typename std::conditional<
95             std::is_lvalue_reference<Type>::value,
96             typename std::remove_reference<Type>::type&&,
97             Type
98         >::type;
99         any_cast<RefType>(static_cast<any&&>(a));
100         assert(false);
101     } catch (bad_any_cast const &) {
102             // do nothing
103     } catch (...) {
104         assert(false);
105     }
106 #else
107     ((void)a);
108 #endif
109 }
110 
test_cast_empty()111 void test_cast_empty() {
112     // None of these operations should allocate.
113     DisableAllocationGuard g; ((void)g);
114     any a;
115     checkThrows<int>(a);
116 }
117 
118 template <class Type>
test_cast_to_reference()119 void test_cast_to_reference() {
120     assert(Type::count == 0);
121     Type::reset();
122     {
123         any a((Type(42)));
124         any const& ca = a;
125         assert(Type::count == 1);
126         assert(Type::copied == 0);
127         assert(Type::moved == 1);
128 
129         // Try a cast to a bad type.
130         // NOTE: Type cannot be an int.
131         checkThrows<int>(a);
132         checkThrows<int&, int const&>(a);
133         checkThrows<Type*, Type const*>(a);
134         checkThrows<Type const*>(a);
135 
136         // Check getting a type by reference from a non-const lvalue any.
137         {
138             Type& v = any_cast<Type&>(a);
139             assert(v.value == 42);
140 
141             Type const &cv = any_cast<Type const&>(a);
142             assert(&cv == &v);
143         }
144         // Check getting a type by reference from a const lvalue any.
145         {
146             Type const& v = any_cast<Type const&>(ca);
147             assert(v.value == 42);
148 
149             Type const &cv = any_cast<Type const&>(ca);
150             assert(&cv == &v);
151         }
152         // Check getting a type by reference from a const rvalue any.
153         {
154             Type const& v = any_cast<Type const&>(std::move(ca));
155             assert(v.value == 42);
156 
157             Type const &cv = any_cast<Type const&>(std::move(ca));
158             assert(&cv == &v);
159         }
160         // Check getting a type by reference from a const rvalue any.
161         {
162             Type&& v = any_cast<Type&&>(std::move(a));
163             assert(v.value == 42);
164             assert(any_cast<Type&>(a).value == 42);
165 
166             Type&& cv = any_cast<Type&&>(std::move(a));
167             assert(&cv == &v);
168             assert(any_cast<Type&>(a).value == 42);
169         }
170         // Check getting a type by reference from a const rvalue any.
171         {
172             Type const&& v = any_cast<Type const&&>(std::move(a));
173             assert(v.value == 42);
174             assert(any_cast<Type&>(a).value == 42);
175 
176             Type const&& cv = any_cast<Type const&&>(std::move(a));
177             assert(&cv == &v);
178             assert(any_cast<Type&>(a).value == 42);
179         }
180         // Check that the original object hasn't been changed.
181         assertContains<Type>(a, 42);
182 
183         // Check that no objects have been created/copied/moved.
184         assert(Type::count == 1);
185         assert(Type::copied == 0);
186         assert(Type::moved == 1);
187     }
188     assert(Type::count == 0);
189 }
190 
191 template <class Type>
test_cast_to_value()192 void test_cast_to_value() {
193     assert(Type::count == 0);
194     Type::reset();
195     {
196         any a((Type(42)));
197         assert(Type::count == 1);
198         assert(Type::copied == 0);
199         assert(Type::moved == 1);
200 
201         // Try a cast to a bad type.
202         // NOTE: Type cannot be an int.
203         checkThrows<int>(a);
204         checkThrows<int&, int const&>(a);
205         checkThrows<Type*, Type const*>(a);
206         checkThrows<Type const*>(a);
207 
208         Type::reset(); // NOTE: reset does not modify Type::count
209         // Check getting Type by value from a non-const lvalue any.
210         // This should cause the non-const copy constructor to be called.
211         {
212             Type t = any_cast<Type>(a);
213 
214             assert(Type::count == 2);
215             assert(Type::copied == 1);
216             assert(Type::const_copied == 0);
217             assert(Type::non_const_copied == 1);
218             assert(Type::moved == 0);
219             assert(t.value == 42);
220         }
221         assert(Type::count == 1);
222         Type::reset();
223         // Check getting const Type by value from a non-const lvalue any.
224         // This should cause the const copy constructor to be called.
225         {
226             Type t = any_cast<Type const>(a);
227 
228             assert(Type::count == 2);
229             assert(Type::copied == 1);
230             assert(Type::const_copied == 0);
231             assert(Type::non_const_copied == 1);
232             assert(Type::moved == 0);
233             assert(t.value == 42);
234         }
235         assert(Type::count == 1);
236         Type::reset();
237         // Check getting Type by value from a non-const lvalue any.
238         // This should cause the const copy constructor to be called.
239         {
240             Type t = any_cast<Type>(static_cast<any const&>(a));
241 
242             assert(Type::count == 2);
243             assert(Type::copied == 1);
244             assert(Type::const_copied == 1);
245             assert(Type::non_const_copied == 0);
246             assert(Type::moved == 0);
247             assert(t.value == 42);
248         }
249         assert(Type::count == 1);
250         Type::reset();
251         // Check getting Type by value from a non-const rvalue any.
252         // This should cause the non-const copy constructor to be called.
253         {
254             Type t = any_cast<Type>(static_cast<any &&>(a));
255 
256             assert(Type::count == 2);
257             assert(Type::moved == 1);
258             assert(Type::copied == 0);
259             assert(Type::const_copied == 0);
260             assert(Type::non_const_copied == 0);
261             assert(t.value == 42);
262             assert(any_cast<Type&>(a).value == 0);
263             any_cast<Type&>(a).value = 42; // reset the value
264         }
265         assert(Type::count == 1);
266         Type::reset();
267         // Check getting const Type by value from a non-const rvalue any.
268         // This should cause the const copy constructor to be called.
269         {
270             Type t = any_cast<Type const>(static_cast<any &&>(a));
271 
272             assert(Type::count == 2);
273             assert(Type::copied == 0);
274             assert(Type::const_copied == 0);
275             assert(Type::non_const_copied == 0);
276             assert(Type::moved == 1);
277             assert(t.value == 42);
278             assert(any_cast<Type&>(a).value == 0);
279             any_cast<Type&>(a).value = 42; // reset the value
280         }
281         assert(Type::count == 1);
282         Type::reset();
283         // Check getting Type by value from a const rvalue any.
284         // This should cause the const copy constructor to be called.
285         {
286             Type t = any_cast<Type>(static_cast<any const&&>(a));
287 
288             assert(Type::count == 2);
289             assert(Type::copied == 1);
290             assert(Type::const_copied == 1);
291             assert(Type::non_const_copied == 0);
292             assert(Type::moved == 0);
293             assert(t.value == 42);
294             assert(any_cast<Type&>(a).value == 42);
295         }
296         // Ensure we still only have 1 Type object alive.
297         assert(Type::count == 1);
298 
299         // Check that the original object hasn't been changed.
300         assertContains<Type>(a, 42);
301     }
302     assert(Type::count == 0);
303 }
304 
main()305 int main() {
306     test_cast_is_not_noexcept();
307     test_cast_return_type();
308     test_cast_empty();
309     test_cast_to_reference<small>();
310     test_cast_to_reference<large>();
311     test_cast_to_value<small>();
312     test_cast_to_value<large>();
313 }
314