gpt4 book ai didi

c++ - 没有 RTTI 的 std::any,它是如何工作的?

转载 作者:IT老高 更新时间:2023-10-28 21:34:23 34 4
gpt4 key购买 nike

如果我想使用 std::any,我可以在关闭 RTTI 的情况下使用它。以下示例使用 gcc 的 -fno-rtti 也可以按预期编译和运行。

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 异常。

这是如何实现的,或者这可能只是一个 gcc 功能?

我发现 boost::any 也不需要 RTTI,但我也发现不是如何解决的。 Does boost::any need RTTI? .

深入研究 STL header 本身并没有给我答案。该代码对我来说几乎无法阅读。

最佳答案

TL;DR; std::any持有一个指向模板类的静态成员函数的指针。该函数可以执行许多操作,并且特定于给定类型,因为函数的实际实例取决于类的模板参数。


std::any 的实现在 libstdc++ 中并没有那么复杂,大家可以看看:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any

基本上,std::any有两个东西:

  • 指向(动态)分配的存储的指针;
  • 指向“存储管理器函数”的指针:
void (*_M_manager)(_Op, const any*, _Arg*);

当你构造或分配一个新的 std::any带有 T 类型的对象, _M_manager指向特定于 T 类型的函数(实际上是 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 所需的操作。 .

此外,很容易在 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) 之间的相等性检查。


类(class)_Manager<_Tp>实际上是 _Manager_internal<_Tp> 的别名或 _Manager_external<_Tp>取决于 _Tp .此类也用于std::any 的对象的分配/构造。类。

关于c++ - 没有 RTTI 的 std::any,它是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51361606/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com