| 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 | |