使用未知参数存储和调用成员函数

时间:2019-04-08 10:58:01

标签: c++ lambda c++17 template-meta-programming

我正在尝试存储未知类的,具有未知参数的成员函数,以便稍后调用。

我找到了以下代码片段来获取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的方法。

1 个答案:

答案 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()泄漏了内存。