【发布时间】:2019-12-24 07:14:02
【问题描述】:
最近我正在开发一个ORM,它通过执行以下操作来接受函数的注册:
orm->register_func("NAME", &User::set_name);
所以基本上当数据库返回列NAME 时,ORM 将使用User 中的函数set_name。在开发过程中,我了解了更多关于std::variant 的信息,下面是我如何使用它的一个小例子:
template<typename RET, typename T, typename ...Args>
using FPTR = RET(T::*)(Args...);
template<typename T>
using VARIANT_FPTR = std::variant<FPTR<void, T, const char *>, FPTR<void, T, const unsigned int>, long int>;
FPTR 基本上是一个通用函数指针(假设函数是类成员),VARIANT_FPTR 定义了我可以在 ORM中注册的函数的可能性>.
现在,由于std::variant 类型,我遇到了问题。这是register_func 的实现:
void register_func(std::string name, VARIANT_FPTR<T> ptr)
{
_map.insert(std::make_pair(name, ptr));
}
但是,我得到一个编译错误,因为像 &User::set_name 这样的参数不是 std::variant 类型。
有没有办法让register_func 诱导其参数的类型?
如果没有,还有其他方法可以进行类似的过程吗?
编译错误是:
error: cannot convert ‘<unresolved overloaded function type>’ to ‘VARIANT_FPTR<services::User>’ {aka ‘std::variant<void (services::User::*)(const char*), void (services::User::*)(unsigned int), long int>’}
这是地图定义:
template<typename T> class Orm
{
private:
std::map<std::string, VARIANT_FPTR<T>> _map;
// ...
};
【问题讨论】:
-
你能举一个例子来说明你是如何调用 register_func 的,你得到的确切错误是什么?您可能需要像这样显式构造变体:
VARIANT_FPTR<T>(&User::set_name) -
我完全按照我在第一段代码中显示的方式调用 register_func 并编辑帖子以显示错误。
-
@ClémentJean 然后你可以编写一个帮助模板函数来从类中获取正确的重载。像这样:godbolt.org/z/4T3T4g。这是没有测试的示例代码:godbolt.org/z/-MArdf。如果这解决了问题,我可以用它来更新答案!
-
只是为了确认错误信息的意义,
User::set_name是超载了吧? -
@ClémentJean:不——我说的是“过载”,就像 GCC 所做的那样。
标签: c++ templates c++17 generic-programming c++-standard-library