实现一个可以存储函数参数的仿函数模板

Implementing a Functor Template which can store its function's arguments

我想将任何类型的事件绑定到我正在开发的游戏的 (G)UI 系统的任何类型的函数。

我想在 Functor 模板 class 中存储任何类型的函数及其初始参数,我可以将其绑定到信号绑定索引。绑定到信号绑定的事件一旦出现在事件队列中就会触发它,这将导致调用绑定到该绑定的所有 Functor。

我发现存储函数参数的方法是在仿函数模板中使用 std::tuple,但我需要帮助正确初始化它并在调用函数时正确解包。

这是我目前拥有的:

template<typename R, typename... Args>
class FuncBinding {
private:
    std::tuple<Args...> args;
    R(*fun)(Args...);

public:             
    FuncBinding(R(*pF)(Args...) , Args... pArgs) 
        :fun(pF), args(std::make_tuple<Args...>(pArgs)) {}

    R invoke() {
        return fun(args...);
    }

    R callFunc(Args... pArgs) {
        return fun(pArgs...);
    }
};

如何正确使用参数包 Args 以便...

从初始化的角度来看,tuple 只是另一种 class 类型,因此您只需将 pack 传递给其构造函数即可对其进行初始化:

FuncBinding(R(*pF)(Args...) , Args... pArgs) 
: fun(pF), args(pArgs...)
{ }

或者,更有效:

args(std::forward<Args>(pArgs)...)

我使用 forward 而不是 std::move() 以防某些 Args... 是左值引用类型。


在调用端,有一个名为 std::apply() 的 C++17 函数可以执行您想要的操作:

R invoke() {
    return std::apply(fun, args);
}

它可以在 C++11 中实现。 cppreference 页面包含一个涉及 std::make_index_sequence 的实现,它本身可以在 C++11 中实现(并且此站点上有许多此类实现)。