std::any 没有 RTTI,它是如何工作的?
如果我想使用 std::any
我可以在关闭 RTTI 的情况下使用它.以下示例也使用 -fno-rtti
和 gcc 按预期编译和运行.
If I want to use std::any
I can use it with RTTI switched off. The following example compiles and runs as expected also with -fno-rtti
with gcc.
int main()
{
std::any x;
x=9.9;
std::cout << std::any_cast<double>(x) << std::endl;
}
但是std::any
是如何存储类型信息的呢?如我所见,如果我使用错误"类型调用 std::any_cast
,我会按预期得到 std::bad_any_cast
异常.
But how std::any
stores the type information? As I see, if I call std::any_cast
with the "wrong" type I got std::bad_any_cast
exception as expected.
这是如何实现的,或者这可能只是 gcc 功能?
How is that realized or is this maybe only a gcc feature?
我发现 boost::any
也不需要 RTTI,但我也没有发现它是如何解决的.boost::any 需要 RTTI 吗?.
I found that boost::any
did also not need RTTI, but I found also not how that is solved. Does boost::any need RTTI?.
深入研究 STL 标头本身并没有给我答案.这段代码对我来说几乎无法阅读.
Digging into the STL header itself gives me no answer. That code is nearly unreadable to me.
推荐答案
TL;DR; std::any
持有一个指向模板化静态成员函数的指针班级.此函数可以执行许多操作,并且特定于给定类型,因为函数的实际实例取决于类的模板参数.
TL;DR; std::any
holds a pointer to a static member function of a templated class. This function can perform many operations and is specific to a given type since the actual instance of the function depends on the template arguments of the class.
libstdc++中std::any
的实现没那么复杂,你可以看看:
The implementation of std::any
in libstdc++ is not that complex, you can have a look at it:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any
基本上,std::any
包含两件事:
Basically, std::any
holds two things:
- 指向(动态)分配的存储的指针;
- 指向存储管理器函数"的指针:
void (*_M_manager)(_Op, const any*, _Arg*);
当你用 T
类型的对象构造或分配一个新的 std::any
时,_M_manager
指向一个特定于type T
(实际上是T
特有的类的静态成员函数):
When you construct or assign a new std::any
with an object of type T
, _M_manager
points to a function specific to the type T
(which is actually a static member function of class specific to T
):
template <typename _ValueType,
typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>, // <-- Class specific to T.
__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
所需的操作.
Since this function is specific to a given type, you don't need RTTI to perform the operations required by std::any
.
此外,在 std::any_cast
中很容易检查您是否正在转换为正确的类型.下面是std::any_cast
的gcc实现的核心:
Furthermore, it is easy to check that you are casting to the right type within std::any_cast
. Here is the core of the gcc implementation of std::any_cast
:
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
).
You can see that it is simply an equality check between the stored function inside the object you are trying to cast (_any->_M_manager
) and the manager function of the type you want to cast to (&any::_Manager<decay_t<_Tp>>::_S_manage
).
_Manager<_Tp>
类实际上是 _Manager_internal<_Tp>
或 _Manager_external<_Tp>
的别名,具体取决于 _Tp
.此类还用于为 std::any
类分配/构造对象.
The class _Manager<_Tp>
is actually an alias to either _Manager_internal<_Tp>
or _Manager_external<_Tp>
depending on _Tp
.
This class is also used for allocation / construction of object for the std::any
class.
相关文章