Kla*_*aus 24 c++ stl rtti c++17
如果我想使用std::any我可以使用RTTI关闭.以下示例-fno-rtti使用gcc 编译并按预期运行.
int main()
{
std::any x;
x=9.9;
std::cout << std::any_cast<double>(x) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是如何std::any存储类型信息?正如我所看到的,如果我std::any_cast使用"错误"类型调用,我会得到std::bad_any_cast预期的异常.
这是如何实现的,或者这可能只是一个gcc功能?
我发现boost::any也不需要RTTI,但我发现也没有解决这个问题.boost :: any需要RTTI吗?.
深入研究STL标题本身并没有给我答案.那段代码对我来说几乎是不可读的.
Hol*_*olt 32
TL; DR; std::any保存指向模板化类的静态成员函数的指针.此函数可以执行许多操作,并且特定于给定类型,因为函数的实际实例取决于类的模板参数.
std::anylibstdc ++中的实现并不复杂,您可以查看它:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/any
基本上,std::any有两件事:
void (*_M_manager)(_Op, const any*, _Arg*);
Run Code Online (Sandbox Code Playgroud)
当您std::any使用类型的对象构造或赋值new 时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) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
由于此函数特定于给定类型,因此您无需RTTI即可执行所需的操作std::any.
此外,很容易检查您是否正在投射到正确的类型std::any_cast.以下是gcc实现的核心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;
}
Run Code Online (Sandbox Code Playgroud)
您可以看到它只是在您尝试cast(_any->_M_manager)的对象内部存储的函数与要转换为(&any::_Manager<decay_t<_Tp>>::_S_manage)的类型的manager函数之间的相等性检查.
该类_Manager<_Tp>实际上是其中一个_Manager_internal<_Tp>或_Manager_external<_Tp>依赖的别名_Tp.该类还用于为类分配/构造对象std::any.
手动实现有限的 RTTI 并不难。您将需要静态泛型函数。我只能说这么多,但没有提供完整的实现。这是一种可能性:
class meta{
static auto id(){
static std::atomic<std::size_t> nextid{};
return ++nextid;//globally unique
};
std::size_t mid=0;//per instance type id
public:
template<typename T>
meta(T&&){
static const std::size_t tid{id()};//classwide unique
mid=tid;
};
meta(meta const&)=default;
meta(meta&&)=default;
meta():mid{}{};
template<typename T>
auto is_a(T&& obj){return mid==meta{obj}.mid;};
};
Run Code Online (Sandbox Code Playgroud)
这是我的第一个观察;离理想还很远,缺少很多细节。人们可以使用 的一个实例meta作为其假定的 实现的非静态数据成员std::any。
| 归档时间: |
|
| 查看次数: |
4104 次 |
| 最近记录: |