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

Posted

技术标签:

【中文标题】实现一个可以存储其函数参数的仿函数模板【英文标题】:Implementing a Functor Template which can store its function's arguments 【发布时间】:2017-09-03 20:56:45 【问题描述】:

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

我想将任何类型的函数及其初始参数存储在 Functor 模板类中,我可以将其绑定到信号绑定索引。绑定到信号绑定的事件一旦出现在事件队列中就会触发它,这将导致绑定到此绑定的所有 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...

...适当地创建模板类std::tuple&lt;Args...&gt; ...用仿函数参数初始化std::tuple&lt;Args...&gt; 实例args ...通过函数指针R(*fun)(Args...)调用函数时解包元组

【问题讨论】:

可能dupe. 【参考方案1】:

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

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 中实现(并且该站点上有许多这样的实现)。

【讨论】:

谢谢。我假设通常首选使用 c++17 解决方案 (std::apply)? @stimulate 如果您使用的是 C++17 编译器,那么可以,直接使用 std::apply() - 它已经为您编写好了。如果没有,那么您将不得不自己实现它——但这并不难。 对于那些感兴趣的人,C++11 index_sequence 的可能实现在这里:***.com/a/24481400/1944004

以上是关于实现一个可以存储其函数参数的仿函数模板的主要内容,如果未能解决你的问题,请参考以下文章

第11课 std::bind和std::function_std::bind绑定器

unordered_map和unordered_set的模拟实现

如何模板化一个接受模板化参数并在 C++ 中对其应用模板化函数的函数?

使用可变参数模板函数围绕类实现基于 pImpl 的包装器

函数模板参数包后跟模板参数和特化

第23课 可变参数模板_Optional和Lazy类的实现