diff options
Diffstat (limited to 'libstdc++-v3/include/experimental/any')
-rw-r--r-- | libstdc++-v3/include/experimental/any | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/libstdc++-v3/include/experimental/any b/libstdc++-v3/include/experimental/any index 641c2cb9c31..fe5c822dd50 100644 --- a/libstdc++-v3/include/experimental/any +++ b/libstdc++-v3/include/experimental/any @@ -300,7 +300,8 @@ inline namespace fundamentals_v1 _Storage _M_storage; template<typename _Tp> - friend void* __any_caster(const any* __any); + friend enable_if_t<is_object<_Tp>::value, void*> + __any_caster(const any* __any); // Manage in-place contained object. template<typename _Tp> @@ -410,19 +411,45 @@ inline namespace fundamentals_v1 } // @} + /// @cond undocumented template<typename _Tp> - void* __any_caster(const any* __any) + enable_if_t<is_object<_Tp>::value, void*> + __any_caster(const any* __any) { - struct _None { }; - using _Up = decay_t<_Tp>; - using _Vp = conditional_t<is_copy_constructible<_Up>::value, _Up, _None>; - if (__any->_M_manager != &any::_Manager<_Vp>::_S_manage) - return nullptr; - any::_Arg __arg; - __any->_M_manager(any::_Op_access, __any, &__arg); - return __arg._M_obj; + // any_cast<T> returns non-null if __any->type() == typeid(T) and + // typeid(T) ignores cv-qualifiers so remove them: + using _Up = remove_cv_t<_Tp>; + // The contained value has a decayed type, so if decay_t<U> is not U, + // then it's not possible to have a contained value of type U. + using __does_not_decay = is_same<decay_t<_Up>, _Up>; + // Only copy constructible types can be used for contained values. + using __is_copyable = is_copy_constructible<_Up>; + // If the type _Tp could never be stored in an any we don't want to + // instantiate _Manager<_Tp>, so use _Manager<any::_Op> instead, which + // is explicitly specialized and has a no-op _S_manage function. + using _Vp = conditional_t<__and_<__does_not_decay, __is_copyable>::value, + _Up, any::_Op>; + // First try comparing function addresses, which works without RTTI + if (__any->_M_manager == &any::_Manager<_Vp>::_S_manage +#if __cpp_rtti + || __any->type() == typeid(_Tp) +#endif + ) + { + any::_Arg __arg; + __any->_M_manager(any::_Op_access, __any, &__arg); + return __arg._M_obj; + } + return nullptr; } + // This overload exists so that std::any_cast<void(*)()>(a) is well-formed. + template<typename _Tp> + enable_if_t<!is_object<_Tp>::value, _Tp*> + __any_caster(const any*) noexcept + { return nullptr; } + /// @endcond + /** * @brief Access the contained object. * @@ -517,6 +544,14 @@ inline namespace fundamentals_v1 } } + // Dummy specialization used by __any_caster. + template<> + struct any::_Manager_internal<any::_Op> + { + static void + _S_manage(_Op, const any*, _Arg*) { } + }; + // @} group any } // namespace fundamentals_v1 } // namespace experimental |