diff options
author | Peter Bergner <bergner@linux.ibm.com> | 2019-10-24 19:17:39 +0000 |
---|---|---|
committer | Peter Bergner <bergner@linux.ibm.com> | 2019-10-24 19:17:39 +0000 |
commit | b3875f87fbe002ad43f35ba5cc16efc80f809883 (patch) | |
tree | ecb74be9e46fcebac6dcaa2e911693b9b70891bf /libstdc++-v3/include/experimental/any | |
parent | d3f50b70a40ea3518d7e386300c4e26e19924ad5 (diff) | |
parent | d844b1d496ef9602a263834327aa73f72663cb6b (diff) |
Merge up to 277354.
* REVISION: Update subversion id.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/ibm/gcc-8-branch@277422 138bc75d-0d04-0410-961f-82ee72b054a4
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 |