TL;DR; std::any
持有一个指向模板类的静态成员函数的指针。这个函数可以执行许多操作,并且特定于给定类型,因为函数的实际实例取决于类的模板参数。
在libstdc++中实现std::any
并不是很复杂,你可以看一下:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any
基本上,{{std::any}}保持两个东西:
- (动态)分配存储的指针;
- 指向“存储管理函数”的指针:
void (*_M_manager)(_Op, const any*, _Arg*);
当您使用类型为T
的对象构造或分配新的std::any
时,_M_manager
指向特定于类型T
的函数(实际上是特定于T
的类的静态成员函数):
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) { }
由于此函数特定于给定类型,因此您不需要RTTI执行std::any
所需的操作。
此外,在std::any_cast
内轻松检查是否将其转换为正确的类型。以下是std::any_cast
的gcc实现核心:
template<typename _Tp>
void* __any_caster(const any* __any) {
if constexpr (is_copy_constructible_v<decay_t<_Tp>>) {
if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage) {
any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg);
return __arg._M_obj;
}
}
return nullptr;
}
你可以看到这只是一个等式检查,检查的是你要转换的对象里存储的函数 (
_any->_M_manager
) 和你想要转换的类型的管理函数 (
&any::_Manager<decay_t<_Tp>>::_S_manage
) 是否相等。
类
_Manager<_Tp>
实际上是别名,根据
_Tp
的不同,它可以是
_Manager_internal<_Tp>
或
_Manager_external<_Tp>
。
该类还用于为
std::any
类分配/构造对象。
boost::any
不需要它的原因。一般来说,我没有看到其他可能性,除了实现自己的typeinfo,而这个typeinfo不依赖于RTTI。 - bartopany
有一个type()
方法,返回一个type_info
,它真的可以在没有 RTTI 的情况下运行吗? - bipll