使用Variadic模板进行委派

时间:2016-01-13 22:26:14

标签: c++ templates variadic-templates

当事件触发(按键,鼠标等)时,我的应用程序将调用已注册该事件的委托函数。

以下是实施。我试图让'invoke'函数(())成为一个可变参数模板,以便我可以将任何参数传递给它。但是我目前的设置不可能。

我在设计中如何使用可变参数模板的任何想法?

修改更改的代码

template <typename... params>
class EventDelegate
{
public:
    typedef std::function<int(params...)> EDelegate;

    EventDelegate(EDelegate delegate) : delegate(delegate)
    {

    }

    int operator()(params...) const
    {
        return delegate(params...);
    }

private:
    EDelegate delegate;
};

// Not valid because template params are not specified. But each EventDelegate can take different params
std::unordered_multimap<int, EventDelegate> evtRegistry; 

// Example

class Foo
{
public:
    int onLeftClick(GUID sender, Point pos);
    int onKeyDown(char key);
};

// Usage 

... 

evtRegistry[1] = EventDelegate(std::bind(&Foo::onLeftClick, myFoo, std::placeholders::_1, std::placeholders::_2));
evtRegistry[2] = EventDelegate(std::bind(&Foo::onKeyDown, myFoo, std::placeholders::_1));

事件处理:

LRESULT CALLBACK Win32App::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    switch (message)
    {
        case WM_CREATE:
        {
            auto registeredCmps = evtRegistry.equal_range(EVT_INIT);
            for (auto iter = registeredCmps.first; iter != registeredCmps.second; iter++)
                iter->second();
        }
        break;
        case WM_DESTROY:
        {
            auto registeredCmps = evtRegistry.equal_range(EVT_EXIT);
            for (auto iter = registeredCmps.first; iter != registeredCmps.second; iter++)
                iter->second(someParam, someOtherParam);
        }
        break;
        ...

1 个答案:

答案 0 :(得分:0)

我的第一个倾向,也许这里最简单的答案是为每种事件类型创建单独的数据结构。例如:

std::vector< EventDelegate< GUID, Point > > clickRegistry
std::vector< EventDelegate< char > > keyDownRegistry

用法

clickRegistry.push_back( EventDelegate(std::bind(&Foo::onLeftClick, myFoo, std::placeholders::_1, std::placeholders::_2)) );

虽然为什么在直接使用std::function时在此处创建单独的委托尚不清楚。 (我可以看到将来在Delegate类中添加一堆其他实用程序,也许这就是你的意图。)

您希望通过包含所有已注册事件的单个数据结构实现什么目标?