C ++无法找出CRTP观察者模式设计

问题描述

我正在尝试一种模板设计,以允许自动的观察者/观察到的功能我有两个怀疑这个问题的人:

  • 静态继承没有按照我对Observing::notify()的期望进行。
  • 我尝试绑定到模板TYPE::Status类中的enum class的{​​{1}}模板化参数。
TYPE

我以为#include <iostream> #include <set> // Observer base class template <class TYPE> struct Observing { template <class STATUS = TYPE::Status> void notify(STATUS status); protected: // Constructed only through inheritance Observing() { TYPE::subscribe(this); } ~Observing() { TYPE::unsubscribe(this); } }; // Class being observed template <class TYPE> struct Observable { static void subscribe (Observing<TYPE>* obs) { observers.insert(obs); } static void unsubscribe (Observing<TYPE>* obs) { observers.erase(obs); } static std::set<Observing<TYPE>*> observers; }; // Static deFinition of observable object's observers container template <class TYPE> std::set<Observing<TYPE>*> Observable<TYPE>::observers; // Implementation of an observable service struct Service : Observable<Service> { enum class Status { Up,Down }; void broadcast(Status status) { for (Observing<Service>* obs : observers) obs->notify(status); // <--- unable to link `notify()` } }; struct Process: Observing<Service> { void notify(Service::Status status) { switch (status) { case Service::Status::Up: std::cout << "Service is UP\n"; break; case Service::Status::Down: std::cout << "Service is DOWN\n"; break; } } }; int main() { Service service; Process worker; service.broadcast(Service::Status::Up); } 的定义可能为时已晚,但是我尝试将声明放在Process::notify()上方,并将定义放在下方,但随后我必须向前声明Service和无法找到声明Service方法

也许我的方法太复杂了...

解决方法

据我了解,您要实现的功能无法正常工作。在此代码中,编译器只能在结构notify中找到没有正文的Observing函数。因此,链接器稍后会对此抱怨。

 for (Observing<Service>* obs : observers)
     obs->notify(status); // <--- unable to link `notify()`

让我们尝试帮助编译器选择正确的函数。由于我们处于编译时,因此可以使用static_cast。让我们尝试一下:

static_cast<To what?>(obj)->notify(status);

这个问题(对static_cast的答案)的答案只能在运行时获得-这导致我们动态多态。

因此,您必须尝试另一种解决方案:使用运行时多态性或更改类的体系结构。

,

观察者模式的重点是主题不知道观察者的静态类型。您将需要virtual。这意味着notify不能作为模板,您需要修复Observable的成员表示notify的自变量。

template <class TYPE>
struct Observing
{
    using Status = typename TYPE::Status;

    virtual void notify(Status status);
    // ...
};

为了安全起见,请在覆盖override的位置添加

struct Process: Observing<Service>
{
    void notify(Status status) override;
};