【问题标题】:Delegate with Variadic Templates使用可变参数模板进行委托
【发布时间】:2016-01-13 22:26:13
【问题描述】:

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

下面是实现。我正在尝试使“调用”函数 (()) 成为可变参数模板,以便可以将任何参数传递给它。但是我目前的设置低于它是不可能的。

有什么想法可以在这个设计中使用可变参数模板来实现吗?

编辑更改的代码

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;
        ...

【问题讨论】:

  • 不清楚你想如何调用EventDelegate而不知道要传递哪个参数...
  • @Jarod42 哎呀,这是一个错字。我现在就修。那是我之前的实现
  • 尚不清楚在遍历 evtRegistry 中的元素时如何区分事件。在不知道模板实例化的情况下如何调用函数?
  • 你希望如何使用evtRegistry[x]
  • @Jarod42 请参阅编辑以了解事件处理。注意 evtRegistry 是 unordered_multimap

标签: c++ templates variadic-templates


【解决方案1】:

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

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 类添加一堆其他实用程序,也许这就是您的意图)。

你想用一个包含所有注册事件的数据结构来实现什么?

【讨论】:

  • “你想用一个保存所有注册事件的数据结构来实现什么?”,每个程序员都想要实现的;简单、优雅和完美,呵呵
猜你喜欢
  • 1970-01-01
  • 2015-01-18
  • 2014-12-10
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
相关资源
最近更新 更多