我正在尝试存储未知类的,具有未知参数的成员函数,以便稍后调用。
我找到了以下代码片段来获取lambda:
template <auto Fn, typename T, typename R = void, typename... Args>
auto get_cb_inner(T* obj, R (T::*)(Args...) const) {
return [obj](Args... args) -> R {
return (obj->*Fn)(std::forward<Args>(args)...);
};
}
template <auto Fn, typename T>
auto get_cb(T* obj) {
return get_cb_inner<Fn, T>(obj, Fn);
}
但是我不知道如何存储它,然后能够在运行时使用正确的参数调用它。
我有一个这样的结构:
struct Job {
void execute(Data& data, const OtherData& otherData) const {
// do job
}
};
auto exe_fn = get_cb<&Job::execute>(new Job());
我要做的是将此“执行”函数存储在lambda中,然后将其存储在可迭代和调用的类似矢量的容器中(带有可能具有不同参数的其他函数)。
编辑:
使用@KamilCuk代码,我创建了该包装器结构,而没有内存泄漏/段错误。
template <typename... Args>
using exec_fn = std::function<void(Args...)>;
template <typename Job>
using job_ptr = std::unique_ptr<Job>;
template <typename J, typename R = void, typename... Args>
struct JobExecuteCaller {
exec_fn<Args...> exec_fn;
job_ptr<J> job_ptr;
JobExecuteCaller (J* job, R (S::*f)(Args...) const)
: job_ptr{job_ptr<J>(job)} {
exec_fn = [this, f](Args... args) -> R {
(job_ptr.get()->*f)(std::forward<Args>(args)...);
};
}
void operator()(Args... args) { exec_fn(args...); }
};
auto process = JobExecuteCaller(new Job(), &Job::execute);
JobExecuteCaller(/*args ... */)
现在,我只需要找出一种存储各种JobExecuteCallers的方法。
答案 0 :(得分:1)
您是说要std::bind
?
#include <utility>
#include <new>
#include <iostream>
#include <functional>
struct Job {
void execute(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
auto exe_fn = std::bind(&Job::execute, new Job(),
std::placeholders::_1, std::placeholders::_2);
exe_fn(1, 2);
}
我已修复您的代码。您不仅需要将函数成员指针的类型传递给函数,还需要将函数成员指针的地址传递给函数。这样就可以调用它。
#include <utility>
#include <new>
#include <iostream>
#include <functional>
template <typename T, typename R = void, typename... Args>
auto get_cb(T* obj, R (T::*f)(Args...)) {
return [obj, f](Args... args) -> R {
return (obj->*f)(std::forward<Args>(args)...);
};
}
struct Job {
void execute(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
auto exe_fn = get_cb(new Job(), &Job::execute);
exe_fn(1, 2);
}
请注意,两个示例都从new Job()
泄漏了内存。