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
31using std::experimental::any;
32using std::experimental::any_cast;
33using std::experimental::bad_any_cast;
34
35
36// Test that the operators are NOT marked noexcept.
37void 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.
45void 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
71template <class Type, class ConstT = Type>
72void 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
106void test_cast_empty() {
107    // None of these operations should allocate.
108    DisableAllocationGuard g; ((void)g);
109    any a;
110    checkThrows<int>(a);
111}
112
113template <class Type>
114void 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
175template <class Type>
176void 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.
286void 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
301int 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