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