重写同一模板化基类的常用方法多次继承

def*_*nst 5 c++ templates multiple-inheritance

背景

我遇到过我可以访问方法的应用程序:

 void AttachCallback(int event, std::functional<void(int)> cb);
Run Code Online (Sandbox Code Playgroud)

这让我可以附加一个回调cb事件event.我还有几个类需要将回调附加到其构造函数中的几个事件,并为它们绑定的每个事件实现回调.因此,首先想到的实现看起来像:

class MyClass {
 public:
  MyClass() {
    AttachCallback(0, [this](int value) { cb0(value); });
    AttachCallback(2, [this](int value) { cb2(value); });
    // ... as necessary
  }
 private:
  void cb0(int value) { /*... callback for event 0 ...*/ }
  void cb2(int value) { /*... callback for event 2 ...*/ }
  // ... as necessary
};
Run Code Online (Sandbox Code Playgroud)

但是,由于我最近一直在玩模板很多,我想知道我是否可以创建一个模板化的纯虚拟类来监听给定的事件并使用它如下:

template<const int EVENT>
class ListensToEvent {
 public:
  virtual ~ListensToEvent() = default;

 protected:
  ListensToEvent() {
    AttachCallback(EVENT, [this](int value) { cb(value); });
  }
  virtual void cb(int value) = 0;
};

class MyClass : public ListensToEvent<0>, public ListensToEvent<2> {
 private:
  void cb(int value) override;
};

template<>  // This line makes me suspicious
void MyClass::ListensToEvent<0>::cb(int value) {
  /*... callback for event 0 ...*/
}
template<>
void MyClass::ListensToEvent<2>::cb(int value) {
  /*... callback for event 2 ...*/
}
Run Code Online (Sandbox Code Playgroud)

在搜索相关主题时,我发现这个线程显示了如何使用辅助类来修复当两个基本接口提供相同标识符纯虚方法时发生的冲突.因为我在这里使用模板,所以我不能使用这样的帮助器,因为我不知道可能有多少个实例,但我发现在没有特化的情况下声明方法然后在类定义之外提供模板特化允许我单独定位每个基类的方法(如上所示).

概念证明

在测试时,我构建了这种设计的简化(没有回调),只是为了表明它在这里编译和专门化.

首先,我关心的是我对它的工作原理的理解.这是有道理的,我认为我将能够指定cb由排位赛我的类定义后实现cb与任一ListensToEvent<0>ListensToEvent<2>.我不明白的是,为什么该资格认定为模板专业化,因此template<>需要该行.另外,如果这些资格实际上是模板特化,那么C++究竟如何查看方法特化以及它们为什么有效?

话虽如此,我也对有关此设计功能的评论感兴趣.它是一种简化MyClass的有效方法,也是其他兄弟姐妹的实现,还是我提出的第一种方式更好?或者还有另一种设计在这种情况下效果最好吗?