存储函数指针,并使用c ++中的安全类型检查对其进行调用

问题描述 投票:0回答:1

我正在尝试找出如何使用c ++ 17最优雅地解决此问题的方法(不使用boost!)。我正在开发一个提供UI控件的库。控件应该能够对事件做出反应,并且用户(使用库)应该能够为这些事件添加其处理程序。我想避免使用Command pattern,因为这对于用户来说太复杂了-他只想定义一个函数并将其分配给某些Event和UI控件。这是一些示例代码:

// My library
class Base; // Base class for all the UI controls

class ListBox : public Base {
    // handlers reacting on clicking the item in listbox
    std::vector<std::variant<std::function<void()>, 
                             std::function<void(int)> click_handlers_;
    // handlers reacting on changing the name of the item in listbox
    std::vector<std::variant<std::function<void()>,
                             std::function<void(std::string, std::string)> edit_handlers_;
public:
    void AddHandler(Event ev, const std::function< ? ? ? > handler);
};

// USER's code
int main() {
    ListBox lb;
    lb.AddHandler(Event::Click, [](int index) { DoSomethingWithItem(i); });
    lb.AddHandler(Event::Edit, [](std::string old_name, std::string new_name)
                                     { DoSomethingWithItemNames(old_name, new_name); });
    lb.AddHandler(Event::Edit, []() { DoSomeCleanup(); });
}

Event::Edit类型的事件发生时,它触发需要两个自变量的enum。此后,DoSomethingWithItemNames()完成其工作并处理了事件(至少从用户的角度而言)。

第一个问题:对于每个LisBox事件,我必须定义一个单独的处理程序向量。第二个问题:DoSomeCleanup()方法的第二个参数的类型应该是什么?

是否有任何方法可以统一这些处理程序,以便用户只能使用一个功能ListBox::AddHandler,而不能单独使用AddHandler()AddClickHandler()之类的功能?当然,应该对函数类型进行静态检查,并且任何类型的不匹配都应在编译时报告给用户。是否有一种标准方法来处理整个概念?请记住,每个控件都有其事件,我的想法是,可以为每个事件分配一个不带参数的处理函数。谢谢。

c++ events c++17 function-pointers variant
1个回答
0
投票

您可以为每种可能性分别设置重载,使用两个变体进行两次重载,或者仅使用类型为AddEditHandler()的参数定义一次,该参数可以使用所有三个可能的std::variant。据我所知,这些是我们当前的选项,不涉及创建从一个基础派生的包装器类,这将再次使它像std::function一样工作。

© www.soinside.com 2019 - 2024. All rights reserved.