1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // template <class ValueType>
14 // ValueType const any_cast(any const&);
16 // template <class ValueType>
17 // ValueType any_cast(any &);
19 // template <class ValueType>
20 // ValueType any_cast(any &&);
23 #include <type_traits>
26 #include "any_helpers.h"
27 #include "count_new.h"
28 #include "test_macros.h"
30 // Test that the operators are NOT marked noexcept.
31 void test_cast_is_not_noexcept() {
33 static_assert(!noexcept(std::any_cast
<int>(static_cast<std::any
&>(a
))), "");
34 static_assert(!noexcept(std::any_cast
<int>(static_cast<std::any
const&>(a
))), "");
35 static_assert(!noexcept(std::any_cast
<int>(static_cast<std::any
&&>(a
))), "");
38 // Test that the return type of any_cast is correct.
39 void test_cast_return_type() {
41 static_assert(std::is_same
<decltype(std::any_cast
<int>(a
)), int>::value
, "");
42 static_assert(std::is_same
<decltype(std::any_cast
<int const>(a
)), int>::value
, "");
43 static_assert(std::is_same
<decltype(std::any_cast
<int&>(a
)), int&>::value
, "");
44 static_assert(std::is_same
<decltype(std::any_cast
<int const&>(a
)), int const&>::value
, "");
45 static_assert(std::is_same
<decltype(std::any_cast
<int&&>(a
)), int&&>::value
, "");
46 static_assert(std::is_same
<decltype(std::any_cast
<int const&&>(a
)), int const&&>::value
, "");
48 static_assert(std::is_same
<decltype(std::any_cast
<int>(std::move(a
))), int>::value
, "");
49 static_assert(std::is_same
<decltype(std::any_cast
<int const>(std::move(a
))), int>::value
, "");
50 static_assert(std::is_same
<decltype(std::any_cast
<int&>(std::move(a
))), int&>::value
, "");
51 static_assert(std::is_same
<decltype(std::any_cast
<int const&>(std::move(a
))), int const&>::value
, "");
52 static_assert(std::is_same
<decltype(std::any_cast
<int&&>(std::move(a
))), int&&>::value
, "");
53 static_assert(std::is_same
<decltype(std::any_cast
<int const&&>(std::move(a
))), int const&&>::value
, "");
55 const std::any
& ca
= a
;
56 static_assert(std::is_same
<decltype(std::any_cast
<int>(ca
)), int>::value
, "");
57 static_assert(std::is_same
<decltype(std::any_cast
<int const>(ca
)), int>::value
, "");
58 static_assert(std::is_same
<decltype(std::any_cast
<int const&>(ca
)), int const&>::value
, "");
59 static_assert(std::is_same
<decltype(std::any_cast
<int const&&>(ca
)), int const&&>::value
, "");
62 template <class Type
, class ConstT
= Type
>
63 void checkThrows(std::any
& a
)
65 #if !defined(TEST_HAS_NO_EXCEPTIONS)
67 TEST_IGNORE_NODISCARD
std::any_cast
<Type
>(a
);
69 } catch (const std::bad_any_cast
&) {
76 TEST_IGNORE_NODISCARD
std::any_cast
<ConstT
>(static_cast<const std::any
&>(a
));
78 } catch (const std::bad_any_cast
&) {
85 using RefType
= typename
std::conditional
<
86 std::is_lvalue_reference
<Type
>::value
,
87 typename
std::remove_reference
<Type
>::type
&&,
90 TEST_IGNORE_NODISCARD
std::any_cast
<RefType
>(static_cast<std::any
&&>(a
));
92 } catch (const std::bad_any_cast
&) {
98 (TEST_IGNORE_NODISCARD a
);
102 void test_cast_empty() {
103 // None of these operations should allocate.
104 DisableAllocationGuard g
; (TEST_IGNORE_NODISCARD g
);
109 template <class Type
>
110 void test_cast_to_reference() {
111 assert(Type::count
== 0);
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);
120 // Try a cast to a bad type.
121 // NOTE: Type cannot be an int.
123 checkThrows
<int&, int const&>(a
);
124 checkThrows
<Type
*, Type
const*>(a
);
125 checkThrows
<Type
const*>(a
);
127 // Check getting a type by reference from a non-const lvalue any.
129 Type
& v
= std::any_cast
<Type
&>(a
);
130 assert(v
.value
== 42);
132 Type
const &cv
= std::any_cast
<Type
const&>(a
);
135 // Check getting a type by reference from a const lvalue any.
137 Type
const& v
= std::any_cast
<Type
const&>(ca
);
138 assert(v
.value
== 42);
140 Type
const &cv
= std::any_cast
<Type
const&>(ca
);
143 // Check getting a type by reference from a const rvalue any.
145 Type
const& v
= std::any_cast
<Type
const&>(std::move(ca
));
146 assert(v
.value
== 42);
148 Type
const &cv
= std::any_cast
<Type
const&>(std::move(ca
));
151 // Check getting a type by reference from a const rvalue any.
153 Type
&& v
= std::any_cast
<Type
&&>(std::move(a
));
154 assert(v
.value
== 42);
155 assert(std::any_cast
<Type
&>(a
).value
== 42);
157 Type
&& cv
= std::any_cast
<Type
&&>(std::move(a
));
159 assert(std::any_cast
<Type
&>(a
).value
== 42);
161 // Check getting a type by reference from a const rvalue any.
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);
167 Type
const&& cv
= std::any_cast
<Type
const&&>(std::move(a
));
169 assert(std::any_cast
<Type
&>(a
).value
== 42);
171 // Check that the original object hasn't been changed.
172 assertContains
<Type
>(a
, 42);
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);
179 assert(Type::count
== 0);
182 template <class Type
>
183 void test_cast_to_value() {
184 assert(Type::count
== 0);
187 std::any a
= Type(42);
188 assert(Type::count
== 1);
189 assert(Type::copied
== 0);
190 assert(Type::moved
== 1);
192 // Try a cast to a bad type.
193 // NOTE: Type cannot be an int.
195 checkThrows
<int&, int const&>(a
);
196 checkThrows
<Type
*, Type
const*>(a
);
197 checkThrows
<Type
const*>(a
);
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.
203 Type t
= std::any_cast
<Type
>(a
);
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);
212 assert(Type::count
== 1);
214 // Check getting const Type by value from a non-const lvalue any.
215 // This should cause the const copy constructor to be called.
217 Type t
= std::any_cast
<Type
const>(a
);
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);
226 assert(Type::count
== 1);
228 // Check getting Type by value from a non-const lvalue any.
229 // This should cause the const copy constructor to be called.
231 Type t
= std::any_cast
<Type
>(static_cast<const std::any
&>(a
));
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);
240 assert(Type::count
== 1);
242 // Check getting Type by value from a non-const rvalue any.
243 // This should cause the non-const copy constructor to be called.
245 Type t
= std::any_cast
<Type
>(static_cast<std::any
&&>(a
));
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
256 assert(Type::count
== 1);
258 // Check getting const Type by value from a non-const rvalue any.
259 // This should cause the const copy constructor to be called.
261 Type t
= std::any_cast
<Type
const>(static_cast<std::any
&&>(a
));
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
272 assert(Type::count
== 1);
274 // Check getting Type by value from a const rvalue any.
275 // This should cause the const copy constructor to be called.
277 Type t
= std::any_cast
<Type
>(static_cast<const std::any
&&>(a
));
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);
287 // Ensure we still only have 1 Type object alive.
288 assert(Type::count
== 1);
290 // Check that the original object hasn't been changed.
291 assertContains
<Type
>(a
, 42);
293 assert(Type::count
== 0);
296 int main(int, char**) {
297 test_cast_is_not_noexcept();
298 test_cast_return_type();
300 test_cast_to_reference
<small
>();
301 test_cast_to_reference
<large
>();
302 test_cast_to_value
<small
>();
303 test_cast_to_value
<large
>();