【发布时间】:2021-12-02 13:33:02
【问题描述】:
我写了下面的代码,
std::unordered_map<std::string_view, std::any> symbols_;
symbols_["foo"] = dlsym(handle_), "foo");
当我使用 any_cast
return (std::any_cast<void(*)()>(symbols_["foo"]))();,程序会抛出错误:bad any_cast。
因为功能,我找到了主要原因。
template<typename _Tp>
void* __any_caster(const any* __any)
判断条件为假,然后返回nullptr。
else if (__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;
}
return nullptr;
我想知道
1.为什么__any->_M_manager == &any::_Manager<_Up>::_S_manage和__any->type() == typeid(_Tp)都是假的,
2.我该如何解决这个问题(继续使用 std::any)。
这是一个简单的演示。
#include <any>
void func() { }
auto main() -> int {
std::any a = (void*)func;
std::any_cast<void(*)()>(a)();
return 1;
}
gcc 版本 10.1.0 (GCC)
【问题讨论】:
-
因为
dlsym(handle_, "foo")的类型不是void(*)()而是void*。 -
您存储了
void*,如果您尝试获取char*或(void*)()之类的不同类型,它会抛出它是不合理的。说真的,你为什么还要问? -
我建议只制作以下类型的地图:
unordered_map<string, void*>。无论如何,您都必须将 reinterpret_cast 用于您期望的函数的 void* 值。 -
@selbie 好吧,
std::any他可以从一开始就存储正确的签名,然后确保每次使用都使用相同的签名。void*做不到。 -
symbols_["foo"] = reinterpret_cast<void(*)()>(dlsym(handle_, "foo"));似乎更合适