c++ - 在 C++ 中创建可装饰的有效事件处理类型

标签 c++ templates boost

在过去的几天里,这真的让我很痛苦。 我实际上有一些类似于 Szymon Gatner 在他的精彩文章中解释的东西,发现 here . (查看演示代码中的 EventHandler 类)

这是我在网络上找到的少数几篇解释得很好的文章之一 如何创建具有可扩展界面的类型。我特别喜欢由此产生的使用语法,非常易于理解。

不过,我还有一件事想用这个类型做,那就是允许它被装饰。现在,用额外的数据成员装饰它是一回事,但我希望装饰也能扩展接口(interface),函数 EventHandler::handleEvent 是唯一需要公开的方法。

现在,不幸的是,EventHandler::registerEventFunc 方法是模板化的。 这意味着我无法在 EventHandler 继承的更多基类(例如 HandlerBase)中将其定义为虚方法。

我的问题是是否有人对如何解决问题(使 EventHandler 可装饰)有任何好的想法。

我试过创建方法

1)

void registerEventFunc(boost::function<void()> * _memFn);

和 2)

void registerEventFunc(boost::function<void(*SomeDerivedEvent*)> * _memFn);

和 3)

void registerEventFunc(boost::function<void(EventBase*)> * __memFn);

对于 1,如果我这样做,我将丢失回调的类 Event 派生参数类型的 typeid。 对于 2,我必须为这个类计划注册的尽可能多的事件回调重载函数 对于 3,多态性在模板参数中不起作用(如果我错了请纠正我)。

我最接近允许将函数虚拟化的是 1, ,但我必须在创建 boost::function 对象时将参数绑定(bind)到 boost::function,并且以后不能在 EventHandler::handleEvent 的主体中对其使用 lambda。

class FooEvent : public Event
{
   public:
   FooEvent(int _val) : Event(), val(_val){}
   int val;
};


class MyHandler : public EventHandler
{
  public:
  MyHandler()
  {
    registerEventFunc(new boost::function<void()>(boost::bind(boost::mem_fn(&MyHandler::onEvent),this, new FooEvent(5))));
  }

  void onEvent(const FooEvent * _event)
  {
    cout << _event->val << endl;
  }

};

最终,我认为这行不通(它无法弄清楚整个 typeInfo 业务来创建 map 查找的键)

任何想法将不胜感激!

如果我以错误的方式解决这个问题,我将不胜感激提及替代方案。 最后的目标当然是拥有一个可以轻松扩展其公共(public)接口(interface)及其数据成员的可装饰类型。 我认为 Szymon 的东西是一个很好的起点,因为它似乎已经完成了第二部分。

提前感谢您的任何帮助。

最佳答案

也许一种选择是创建一个保留类型信息的模板化公共(public)函数,以及一个用于实际注册处理程序的虚拟保护函数。即:

class event_source {
  protected:
    struct EventAdapter {
      virtual void invoke(EventBase *) = 0;
      virtual ~EventAdapter() { }
    };
    template<typename EventParam>
    struct EventAdapterInst : public EventAdapter {
      boost::function<void(const EventParam &)> func_;

      EventAdapterInst(const boost::function<void(const EventParam &)> &func)
        : func_(func)
      { }

      virtual void invoke(EventBase *eb) {
        EventParam *param = dynamic_cast<EventParam *>(eb);
        assert(param);
        func_(*param);        
      }
    };
    virtual void register_handler(std::type_info param_type, EventAdapter *ea);
  public:
    template<typename EventParam>
      void register_handler(const boost::function<const EventParam &> &handler)
      {
        register_handler(typeid(EventParam), new EventAdapterInst(handler));
      }
};

派生类可以重写虚拟 register_handler 来做任何他们想做的事,而不会破坏模板函数的类型推断属性。

关于c++ - 在 C++ 中创建可装饰的有效事件处理类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6756155/

相关文章:

c++ - C++中的复合赋值

c++ - MPI_Send 发送数组地址还是数组内容

c++ - 模板中的从属名称和非从属名称

c++ - 如何实例化模板类的模板

c++ - 使用部分特化从 boost:hana::set 中提取类型失败

c++ - 如何 fold STL 容器?

c++ - 无法使用 Boost.Filesystem 链接程序

c++ - 一个代码中for循环的不同迭代器

c++ - 用于访问多态类型的 std::visit-like 函数

c++ - Visual C++ 编译器允许从属名称作为没有 "typename"的类型?