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 *) noexcept; |
15 | // |
16 | // template <class ValueType> |
17 | // ValueType * any_cast(any *) noexcept; |
18 | |
19 | #include <any> |
20 | #include <type_traits> |
21 | #include <cassert> |
22 | |
23 | #include "test_macros.h" |
24 | #include "any_helpers.h" |
25 | |
26 | // Test that the operators are properly noexcept. |
27 | void test_cast_is_noexcept() { |
28 | std::any a; |
29 | ASSERT_NOEXCEPT(std::any_cast<int>(any: &a)); |
30 | |
31 | const std::any& ca = a; |
32 | ASSERT_NOEXCEPT(std::any_cast<int>(any: &ca)); |
33 | } |
34 | |
35 | // Test that the return type of any_cast is correct. |
36 | void test_cast_return_type() { |
37 | std::any a; |
38 | ASSERT_SAME_TYPE(decltype(std::any_cast<int>(&a)), int*); |
39 | ASSERT_SAME_TYPE(decltype(std::any_cast<int const>(&a)), int const*); |
40 | |
41 | const std::any& ca = a; |
42 | ASSERT_SAME_TYPE(decltype(std::any_cast<int>(&ca)), int const*); |
43 | ASSERT_SAME_TYPE(decltype(std::any_cast<int const>(&ca)), int const*); |
44 | } |
45 | |
46 | // Test that any_cast handles null pointers. |
47 | void test_cast_nullptr() { |
48 | std::any *a = nullptr; |
49 | assert(nullptr == std::any_cast<int>(a)); |
50 | assert(nullptr == std::any_cast<int const>(a)); |
51 | |
52 | const std::any *ca = nullptr; |
53 | assert(nullptr == std::any_cast<int>(ca)); |
54 | assert(nullptr == std::any_cast<int const>(ca)); |
55 | } |
56 | |
57 | // Test casting an empty object. |
58 | void test_cast_empty() { |
59 | { |
60 | std::any a; |
61 | assert(nullptr == std::any_cast<int>(&a)); |
62 | assert(nullptr == std::any_cast<int const>(&a)); |
63 | |
64 | const std::any& ca = a; |
65 | assert(nullptr == std::any_cast<int>(&ca)); |
66 | assert(nullptr == std::any_cast<int const>(&ca)); |
67 | } |
68 | // Create as non-empty, then make empty and run test. |
69 | { |
70 | std::any a(42); |
71 | a.reset(); |
72 | assert(nullptr == std::any_cast<int>(&a)); |
73 | assert(nullptr == std::any_cast<int const>(&a)); |
74 | |
75 | const std::any& ca = a; |
76 | assert(nullptr == std::any_cast<int>(&ca)); |
77 | assert(nullptr == std::any_cast<int const>(&ca)); |
78 | } |
79 | } |
80 | |
81 | template <class Type> |
82 | void test_cast() { |
83 | assert(Type::count == 0); |
84 | Type::reset(); |
85 | { |
86 | std::any a = Type(42); |
87 | const std::any& ca = a; |
88 | assert(Type::count == 1); |
89 | assert(Type::copied == 0); |
90 | assert(Type::moved == 1); |
91 | |
92 | // Try a cast to a bad type. |
93 | // NOTE: Type cannot be an int. |
94 | assert(std::any_cast<int>(&a) == nullptr); |
95 | assert(std::any_cast<int const>(&a) == nullptr); |
96 | assert(std::any_cast<int const volatile>(&a) == nullptr); |
97 | |
98 | // Try a cast to the right type, but as a pointer. |
99 | assert(std::any_cast<Type*>(&a) == nullptr); |
100 | assert(std::any_cast<Type const*>(&a) == nullptr); |
101 | |
102 | // Check getting a unqualified type from a non-const any. |
103 | Type* v = std::any_cast<Type>(&a); |
104 | assert(v != nullptr); |
105 | assert(v->value == 42); |
106 | |
107 | // change the stored value and later check for the new value. |
108 | v->value = 999; |
109 | |
110 | // Check getting a const qualified type from a non-const any. |
111 | Type const* cv = std::any_cast<Type const>(&a); |
112 | assert(cv != nullptr); |
113 | assert(cv == v); |
114 | assert(cv->value == 999); |
115 | |
116 | // Check getting a unqualified type from a const any. |
117 | cv = std::any_cast<Type>(&ca); |
118 | assert(cv != nullptr); |
119 | assert(cv == v); |
120 | assert(cv->value == 999); |
121 | |
122 | // Check getting a const-qualified type from a const any. |
123 | cv = std::any_cast<Type const>(&ca); |
124 | assert(cv != nullptr); |
125 | assert(cv == v); |
126 | assert(cv->value == 999); |
127 | |
128 | // Check that no more objects were created, copied or moved. |
129 | assert(Type::count == 1); |
130 | assert(Type::copied == 0); |
131 | assert(Type::moved == 1); |
132 | } |
133 | assert(Type::count == 0); |
134 | } |
135 | |
136 | void test_cast_non_copyable_type() |
137 | { |
138 | // Even though 'any' never stores non-copyable types |
139 | // we still need to support any_cast<NoCopy>(ptr) |
140 | struct NoCopy { NoCopy(NoCopy const&) = delete; }; |
141 | std::any a(42); |
142 | std::any const& ca = a; |
143 | assert(std::any_cast<NoCopy>(&a) == nullptr); |
144 | assert(std::any_cast<NoCopy>(&ca) == nullptr); |
145 | } |
146 | |
147 | void test_cast_array() { |
148 | int arr[3]; |
149 | std::any a(arr); |
150 | RTTI_ASSERT(a.type() == typeid(int*)); // contained value is decayed |
151 | // We can't get an array out |
152 | int (*p)[3] = std::any_cast<int[3]>(any: &a); |
153 | assert(p == nullptr); |
154 | } |
155 | |
156 | void test_fn() {} |
157 | |
158 | void test_cast_function_pointer() { |
159 | using T = void(*)(); |
160 | std::any a(test_fn); |
161 | // An any can never store a function type, but we should at least be able |
162 | // to ask. |
163 | assert(std::any_cast<void()>(&a) == nullptr); |
164 | T fn_ptr = std::any_cast<T>(any&: a); |
165 | assert(fn_ptr == test_fn); |
166 | } |
167 | |
168 | int main(int, char**) { |
169 | test_cast_is_noexcept(); |
170 | test_cast_return_type(); |
171 | test_cast_nullptr(); |
172 | test_cast_empty(); |
173 | test_cast<small>(); |
174 | test_cast<large>(); |
175 | test_cast_non_copyable_type(); |
176 | test_cast_array(); |
177 | test_cast_function_pointer(); |
178 | |
179 | return 0; |
180 | } |
181 | |