| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| |
| // <any> |
| |
| // template <class ValueType> |
| // ValueType const* any_cast(any const *) noexcept; |
| // |
| // template <class ValueType> |
| // ValueType * any_cast(any *) noexcept; |
| |
| #include <any> |
| #include <type_traits> |
| #include <cassert> |
| |
| #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<int>(&a)); |
| |
| any const& ca = a; |
| ASSERT_NOEXCEPT(any_cast<int>(&ca)); |
| } |
| |
| // Test that the return type of any_cast is correct. |
| void test_cast_return_type() { |
| any a; |
| ASSERT_SAME_TYPE(decltype(any_cast<int>(&a)), int*); |
| ASSERT_SAME_TYPE(decltype(any_cast<int const>(&a)), int const*); |
| |
| any const& ca = a; |
| ASSERT_SAME_TYPE(decltype(any_cast<int>(&ca)), int const*); |
| ASSERT_SAME_TYPE(decltype(any_cast<int const>(&ca)), int const*); |
| } |
| |
| // Test that any_cast handles null pointers. |
| void test_cast_nullptr() { |
| any* a = nullptr; |
| assert(nullptr == any_cast<int>(a)); |
| assert(nullptr == any_cast<int const>(a)); |
| |
| any const* ca = nullptr; |
| assert(nullptr == any_cast<int>(ca)); |
| assert(nullptr == any_cast<int const>(ca)); |
| } |
| |
| // Test casting an empty object. |
| void test_cast_empty() { |
| { |
| any a; |
| assert(nullptr == any_cast<int>(&a)); |
| assert(nullptr == any_cast<int const>(&a)); |
| |
| any const& ca = a; |
| assert(nullptr == any_cast<int>(&ca)); |
| assert(nullptr == any_cast<int const>(&ca)); |
| } |
| // Create as non-empty, then make empty and run test. |
| { |
| any a(42); |
| a.reset(); |
| assert(nullptr == any_cast<int>(&a)); |
| assert(nullptr == any_cast<int const>(&a)); |
| |
| any const& ca = a; |
| assert(nullptr == any_cast<int>(&ca)); |
| assert(nullptr == any_cast<int const>(&ca)); |
| } |
| } |
| |
| template <class Type> |
| 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<int>(&a) == nullptr); |
| assert(any_cast<int const>(&a) == nullptr); |
| assert(any_cast<int const volatile>(&a) == nullptr); |
| |
| // Try a cast to the right type, but as a pointer. |
| assert(any_cast<Type*>(&a) == nullptr); |
| assert(any_cast<Type const*>(&a) == nullptr); |
| |
| // Check getting a unqualified type from a non-const any. |
| Type* v = any_cast<Type>(&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<Type const>(&a); |
| assert(cv != nullptr); |
| assert(cv == v); |
| assert(cv->value == 999); |
| |
| // Check getting a unqualified type from a const any. |
| cv = any_cast<Type>(&ca); |
| assert(cv != nullptr); |
| assert(cv == v); |
| assert(cv->value == 999); |
| |
| // Check getting a const-qualified type from a const any. |
| cv = any_cast<Type const>(&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<NoCopy>(ptr) |
| struct NoCopy { NoCopy(NoCopy const&) = delete; }; |
| std::any a(42); |
| std::any const& ca = a; |
| assert(std::any_cast<NoCopy>(&a) == nullptr); |
| assert(std::any_cast<NoCopy>(&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<int[3]>(&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<void()>(&a) == nullptr); |
| T fn_ptr = std::any_cast<T>(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<small>(); |
| test_cast<large>(); |
| test_cast_non_copyable_type(); |
| test_cast_array(); |
| test_cast_function_pointer(); |
| |
| return 0; |
| } |