diff options
Diffstat (limited to 'libcxx')
| -rw-r--r-- | libcxx/include/any | 20 | ||||
| -rw-r--r-- | libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp | 13 |
2 files changed, 29 insertions, 4 deletions
diff --git a/libcxx/include/any b/libcxx/include/any index 7f2cf1ef2b4..229daca9cd9 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -622,6 +622,18 @@ any_cast(any const * __any) _NOEXCEPT return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any)); } +template <class _RetType> +inline _LIBCPP_INLINE_VISIBILITY +_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { + return static_cast<_RetType>(__p); +} + +template <class _RetType> +inline _LIBCPP_INLINE_VISIBILITY +_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { + return nullptr; +} + template <class _ValueType> add_pointer_t<_ValueType> any_cast(any * __any) _NOEXCEPT @@ -631,15 +643,15 @@ any_cast(any * __any) _NOEXCEPT "_ValueType may not be a reference."); typedef typename add_pointer<_ValueType>::type _ReturnType; if (__any && __any->__h) { - return static_cast<_ReturnType>( - __any->__call(_Action::_Get, nullptr, + void *__p = __any->__call(_Action::_Get, nullptr, #if !defined(_LIBCPP_NO_RTTI) &typeid(_ValueType), #else nullptr, #endif - __any_imp::__get_fallback_typeid<_ValueType>() - )); + __any_imp::__get_fallback_typeid<_ValueType>()); + return _VSTD::__pointer_or_func_cast<_ReturnType>( + __p, is_function<_ValueType>{}); } return nullptr; } diff --git a/libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp b/libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp index 0f4fc6ab7eb..1a5a85482b8 100644 --- a/libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp +++ b/libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp @@ -147,6 +147,18 @@ void test_cast_non_copyable_type() assert(std::any_cast<NoCopy>(&ca) == 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() { test_cast_is_noexcept(); test_cast_return_type(); @@ -155,4 +167,5 @@ int main() { test_cast<small>(); test_cast<large>(); test_cast_non_copyable_type(); + test_cast_function_pointer(); } |

