//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 // XFAIL: dylib-has-no-bad_any_cast && !libcpp-no-exceptions // // template // ValueType const* any_cast(any const *) noexcept; // // template // ValueType * any_cast(any *) noexcept; #include #include #include #include "test_macros.h" #include "any_helpers.h" using std::any; using std::any_cast; // Test that the operators are properly noexcept. void test_cast_is_noexcept() { any a; ASSERT_NOEXCEPT(any_cast(&a)); any const& ca = a; ASSERT_NOEXCEPT(any_cast(&ca)); } // Test that the return type of any_cast is correct. void test_cast_return_type() { any a; ASSERT_SAME_TYPE(decltype(any_cast(&a)), int*); ASSERT_SAME_TYPE(decltype(any_cast(&a)), int const*); any const& ca = a; ASSERT_SAME_TYPE(decltype(any_cast(&ca)), int const*); ASSERT_SAME_TYPE(decltype(any_cast(&ca)), int const*); } // Test that any_cast handles null pointers. void test_cast_nullptr() { any* a = nullptr; assert(nullptr == any_cast(a)); assert(nullptr == any_cast(a)); any const* ca = nullptr; assert(nullptr == any_cast(ca)); assert(nullptr == any_cast(ca)); } // Test casting an empty object. void test_cast_empty() { { any a; assert(nullptr == any_cast(&a)); assert(nullptr == any_cast(&a)); any const& ca = a; assert(nullptr == any_cast(&ca)); assert(nullptr == any_cast(&ca)); } // Create as non-empty, then make empty and run test. { any a(42); a.reset(); assert(nullptr == any_cast(&a)); assert(nullptr == any_cast(&a)); any const& ca = a; assert(nullptr == any_cast(&ca)); assert(nullptr == any_cast(&ca)); } } template void test_cast() { assert(Type::count == 0); Type::reset(); { any a((Type(42))); any const& ca = a; assert(Type::count == 1); assert(Type::copied == 0); assert(Type::moved == 1); // Try a cast to a bad type. // NOTE: Type cannot be an int. assert(any_cast(&a) == nullptr); assert(any_cast(&a) == nullptr); assert(any_cast(&a) == nullptr); // Try a cast to the right type, but as a pointer. assert(any_cast(&a) == nullptr); assert(any_cast(&a) == nullptr); // Check getting a unqualified type from a non-const any. Type* v = any_cast(&a); assert(v != nullptr); assert(v->value == 42); // change the stored value and later check for the new value. v->value = 999; // Check getting a const qualified type from a non-const any. Type const* cv = any_cast(&a); assert(cv != nullptr); assert(cv == v); assert(cv->value == 999); // Check getting a unqualified type from a const any. cv = any_cast(&ca); assert(cv != nullptr); assert(cv == v); assert(cv->value == 999); // Check getting a const-qualified type from a const any. cv = any_cast(&ca); assert(cv != nullptr); assert(cv == v); assert(cv->value == 999); // Check that no more objects were created, copied or moved. assert(Type::count == 1); assert(Type::copied == 0); assert(Type::moved == 1); } assert(Type::count == 0); } void test_cast_non_copyable_type() { // Even though 'any' never stores non-copyable types // we still need to support any_cast(ptr) struct NoCopy { NoCopy(NoCopy const&) = delete; }; std::any a(42); std::any const& ca = a; assert(std::any_cast(&a) == nullptr); assert(std::any_cast(&ca) == nullptr); } void test_cast_array() { int arr[3]; std::any a(arr); assert(a.type() == typeid(int*)); // contained value is decayed // We can't get an array out int (*p)[3] = std::any_cast(&a); assert(p == nullptr); } void test_fn() {} void test_cast_function_pointer() { using T = void(*)(); std::any a(test_fn); // An any can never store a function type, but we should at least be able // to ask. assert(std::any_cast(&a) == nullptr); T fn_ptr = std::any_cast(a); assert(fn_ptr == test_fn); } int main(int, char**) { test_cast_is_noexcept(); test_cast_return_type(); test_cast_nullptr(); test_cast_empty(); test_cast(); test_cast(); test_cast_non_copyable_type(); test_cast_array(); test_cast_function_pointer(); return 0; }