【发布时间】:2014-05-05 22:46:37
【问题描述】:
在代码中,我在管理器类中注册了一个或多个函数指针。
在这个类中,我有一个将函数的参数类型映射到所述函数的映射。它可能看起来像这样:std::map< std::vector<std::type_index> , void*>
template<typename Ret, typename... Args>
void Register(Ret(*function)(Args...)) {
void* v = (void*)function;
// recursively build type vector and add to the map
}
在运行时,代码会收到带有任意数量参数的调用(来自外部脚本)。这些参数可以读取为原始数据类型或将在编译时指定的自定义类型。
对于脚本的每次调用,我都必须找出要调用的函数,然后调用它。前者很容易并且已经解决(在循环中用type_index 填充向量),但我想不出后者的解决方案。
我的第一种方法是在递归中使用可变参数模板,并为每个读取类型添加模板参数 - 但结果证明这是不可能的,因为模板是在编译时构建的,并且在运行时读取任意数量的参数。
但是,如果没有可变参数模板,我看不到任何实现这一目标的可能性。我考虑过boost::any 而不是void*,但我没有看到这将如何解决转换回原始类型的需要。我也想过使用std::function,但这将是一个模板类型,因此它不能存储在具有不同参数的函数的映射中。
(如果不清楚我在问什么,请考虑 LuaBinds 到 register overloaded functions 的可能性。我试图了解它是如何在那里实现的(没有可变参数模板,C++11 之前的),但是没用。)
【问题讨论】:
-
也许吧? codereview.stackexchange.com/questions/46473/… 不确定这是否相似。我认为您可能正朝着编写解释器的方向前进。但不确定。
-
顺便说一句,posix需要在
void*和函数指针之间进行转换,但是标准C和C++不支持。 -
@Cheersandhth.-Alf 感谢您的意见,虽然it compiled without errors,但我不知道。一个类似(一致)的方法是存储一个指向模板类的虚拟基类的指针,该模板类存储实际的函数指针,尽管这最终会导致需要相同转换的相同问题。我根本不喜欢
void*/casting 解决方案!这正是我能想到的。 -
我认为您正在寻找类型擦除。 AFAIK 最简单的实现是使用包装函数模板,该模板将实际类型存储在其模板参数中:
template<class T> void wrapper(void* p) { static_cast<T*>(p)->whatever(); } void(*f)(void*) = wrapper<MyFirstType>; f = wrapper<MySecondType>;等。 -
你不是在复制
std::function和std::bind的功能吗?
标签: c++ templates c++11 variadic-templates type-erasure