摘要: 本文介绍了std::any的基本原理与源码实现,包括简化版TinyAny的设计思路,利用类型擦除和静态管理函数实现存储与操作,强调其非类型安全特性。详细分析了std::any的存储结构(联合体_Storage)、类型管理(_Manager模板及其内部实现)、类型信息(typeid)以及类型转换(any_cast)的实现机制,展示了其在小对象优化、堆存储、类型识别和运行时类型安全保障方面的设计思想。 (评价: A)
std::any是C++17定义的支持任意可拷贝类型的标准容器. 描述如下:
The class any describes a type-safe container for single values of any copy constructible type.
// Holds either pointer to a heap object or the contained object itself.
union_Storage{constexpr_Storage():_M_ptr{nullptr}{}// Prevent trivial copies of this type, buffer might hold a non-POD.
_Storage(const_Storage&)=delete;_Storage&operator=(const_Storage&)=delete;void*_M_ptr;aligned_storage<sizeof(_M_ptr),alignof(void*)>::type_M_buffer;};
// other transformations [4.8].
template<std::size_t_Len,std::size_t_Align>structaligned_storage{uniontype{unsignedchar__data[_Len];struct__attribute__((__aligned__((_Align)))){}__align;};};
/// Construct with a copy of @p __value as the contained object.
template<typename_ValueType,typename_Tp=_Decay<_ValueType>,typename_Mgr=_Manager<_Tp>,__any_constructible_t<_Tp,_ValueType&&>=true,enable_if_t<!__is_in_place_type<_Tp>::value,bool>=true>any(_ValueType&&__value):_M_manager(&_Mgr::_S_manage){_Mgr::_S_create(_M_storage,std::forward<_ValueType>(__value));}
template<typename_Tp>voidany::_Manager_external<_Tp>::_S_manage(_Op__which,constany*__any,_Arg*__arg){// The contained object is *_M_storage._M_ptr
auto__ptr=static_cast<const_Tp*>(__any->_M_storage._M_ptr);switch(__which){case_Op_access:__arg->_M_obj=const_cast<_Tp*>(__ptr);break;case_Op_get_type_info:#if __cpp_rtti
__arg->_M_typeinfo=&typeid(_Tp);#endif
break;case_Op_clone:__arg->_M_any->_M_storage._M_ptr=new_Tp(*__ptr);__arg->_M_any->_M_manager=__any->_M_manager;break;case_Op_destroy:delete__ptr;break;case_Op_xfer:__arg->_M_any->_M_storage._M_ptr=__any->_M_storage._M_ptr;__arg->_M_any->_M_manager=__any->_M_manager;const_cast<any*>(__any)->_M_manager=nullptr;break;}}
template<typename_Tp>void*__any_caster(constany*__any){// 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:
ifconstexpr(!is_same_v<decay_t<_Up>,_Up>)returnnullptr;// Only copy constructible types can be used for contained values:
elseifconstexpr(!is_copy_constructible_v<_Up>)returnnullptr;// First try comparing function addresses, which works without RTTI
elseif(__any->_M_manager==&any::_Manager<_Up>::_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;}returnnullptr;}