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

source code of libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp