summaryrefslogtreecommitdiffstats
path: root/libcxx
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/include/any20
-rw-r--r--libcxx/test/std/utilities/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp13
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();
}
OpenPOWER on IntegriCloud