• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
11 
12 // <experimental/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 <experimental/any>
24 #include <type_traits>
25 #include <cassert>
26 
27 #include "experimental_any_helpers.h"
28 #include "count_new.hpp"
29 #include "test_macros.h"
30 
31 using std::experimental::any;
32 using std::experimental::any_cast;
33 using std::experimental::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         any_cast<Type>(static_cast<any&&>(a));
95         assert(false);
96     } catch (bad_any_cast const &) {
97             // do nothing
98     } catch (...) {
99         assert(false);
100     }
101 #else
102   ((void)a);
103 #endif
104 }
105 
test_cast_empty()106 void test_cast_empty() {
107     // None of these operations should allocate.
108     DisableAllocationGuard g; ((void)g);
109     any a;
110     checkThrows<int>(a);
111 }
112 
113 template <class Type>
test_cast_to_reference()114 void test_cast_to_reference() {
115     assert(Type::count == 0);
116     Type::reset();
117     {
118         any a((Type(42)));
119         any const& ca = a;
120         assert(Type::count == 1);
121         assert(Type::copied == 0);
122         assert(Type::moved == 1);
123 
124         // Try a cast to a bad type.
125         // NOTE: Type cannot be an int.
126         checkThrows<int>(a);
127         checkThrows<int&, int const&>(a);
128         checkThrows<Type*, Type const*>(a);
129         checkThrows<Type const*>(a);
130 
131         // Check getting a type by reference from a non-const lvalue any.
132         {
133             Type& v = any_cast<Type&>(a);
134             assert(v.value == 42);
135 
136             Type const &cv = any_cast<Type const&>(a);
137             assert(&cv == &v);
138         }
139         // Check getting a type by reference from a const lvalue any.
140         {
141             Type const& v = any_cast<Type const&>(ca);
142             assert(v.value == 42);
143 
144             Type const &cv = any_cast<Type const&>(ca);
145             assert(&cv == &v);
146         }
147         // Check getting a type by reference from a non-const rvalue
148         {
149             Type& v = any_cast<Type&>(std::move(a));
150             assert(v.value == 42);
151 
152             Type const &cv = any_cast<Type const&>(std::move(a));
153             assert(&cv == &v);
154         }
155         // Check getting a type by reference from a const rvalue any.
156         {
157             Type const& v = any_cast<Type const&>(std::move(ca));
158             assert(v.value == 42);
159 
160             Type const &cv = any_cast<Type const&>(std::move(ca));
161             assert(&cv == &v);
162         }
163 
164         // Check that the original object hasn't been changed.
165         assertContains<Type>(a, 42);
166 
167         // Check that no objects have been created/copied/moved.
168         assert(Type::count == 1);
169         assert(Type::copied == 0);
170         assert(Type::moved == 1);
171     }
172     assert(Type::count == 0);
173 }
174 
175 template <class Type>
test_cast_to_value()176 void test_cast_to_value() {
177     assert(Type::count == 0);
178     Type::reset();
179     {
180         any a((Type(42)));
181         assert(Type::count == 1);
182         assert(Type::copied == 0);
183         assert(Type::moved == 1);
184 
185         // Try a cast to a bad type.
186         // NOTE: Type cannot be an int.
187         checkThrows<int>(a);
188         checkThrows<int&, int const&>(a);
189         checkThrows<Type*, Type const*>(a);
190         checkThrows<Type const*>(a);
191 
192         Type::reset(); // NOTE: reset does not modify Type::count
193         // Check getting Type by value from a non-const lvalue any.
194         // This should cause the non-const copy constructor to be called.
195         {
196             Type t = any_cast<Type>(a);
197 
198             assert(Type::count == 2);
199             assert(Type::copied == 1);
200             assert(Type::const_copied == 0);
201             assert(Type::non_const_copied == 1);
202             assert(Type::moved == 0);
203             assert(t.value == 42);
204         }
205         assert(Type::count == 1);
206         Type::reset();
207         // Check getting const Type by value from a non-const lvalue any.
208         // This should cause the const copy constructor to be called.
209         {
210             Type t = any_cast<Type const>(a);
211 
212             assert(Type::count == 2);
213             assert(Type::copied == 1);
214             assert(Type::const_copied == 1);
215             assert(Type::non_const_copied == 0);
216             assert(Type::moved == 0);
217             assert(t.value == 42);
218         }
219         assert(Type::count == 1);
220         Type::reset();
221         // Check getting Type by value from a non-const lvalue any.
222         // This should cause the const copy constructor to be called.
223         {
224             Type t = any_cast<Type>(static_cast<any const&>(a));
225 
226             assert(Type::count == 2);
227             assert(Type::copied == 1);
228             assert(Type::const_copied == 1);
229             assert(Type::non_const_copied == 0);
230             assert(Type::moved == 0);
231             assert(t.value == 42);
232         }
233         assert(Type::count == 1);
234         Type::reset();
235         // Check getting Type by value from a non-const rvalue any.
236         // This should cause the non-const copy constructor to be called.
237         {
238             Type t = any_cast<Type>(static_cast<any &&>(a));
239 
240             assert(Type::count == 2);
241             assert(Type::copied == 1);
242             assert(Type::const_copied == 0);
243             assert(Type::non_const_copied == 1);
244             assert(Type::moved == 0);
245             assert(t.value == 42);
246         }
247         assert(Type::count == 1);
248         Type::reset();
249         // Check getting const Type by value from a non-const rvalue any.
250         // This should cause the const copy constructor to be called.
251         {
252             Type t = any_cast<Type const>(static_cast<any &&>(a));
253 
254             assert(Type::count == 2);
255             assert(Type::copied == 1);
256             assert(Type::const_copied == 1);
257             assert(Type::non_const_copied == 0);
258             assert(Type::moved == 0);
259             assert(t.value == 42);
260         }
261         assert(Type::count == 1);
262         Type::reset();
263         // Check getting Type by value from a const rvalue any.
264         // This should cause the const copy constructor to be called.
265         {
266             Type t = any_cast<Type>(static_cast<any const&&>(a));
267 
268             assert(Type::count == 2);
269             assert(Type::copied == 1);
270             assert(Type::const_copied == 1);
271             assert(Type::non_const_copied == 0);
272             assert(Type::moved == 0);
273             assert(t.value == 42);
274         }
275         // Ensure we still only have 1 Type object alive.
276         assert(Type::count == 1);
277 
278         // Check that the original object hasn't been changed.
279         assertContains<Type>(a, 42);
280     }
281     assert(Type::count == 0);
282 }
283 
284 // Even though you can't get a non-copyable class into std::any
285 // the standard requires that these overloads compile and function.
test_non_copyable_ref()286 void test_non_copyable_ref() {
287     struct no_copy
288     {
289         no_copy() {}
290         no_copy(no_copy &&) {}
291     private:
292         no_copy(no_copy const &);
293     };
294 
295     any a;
296     checkThrows<no_copy &, no_copy const&>(a);
297     checkThrows<no_copy const&>(a);
298     assertEmpty(a);
299 }
300 
main()301 int main() {
302     test_cast_is_not_noexcept();
303     test_cast_return_type();
304     test_cast_empty();
305     test_cast_to_reference<small>();
306     test_cast_to_reference<large>();
307     test_cast_to_value<small>();
308     test_cast_to_value<large>();
309     test_non_copyable_ref();
310 }
311