具有动态回调函数类型的 C++ 模板 class

C++ template class with dynamic callback function type

在下面的代码中,我希望用户能够创建具有特定类型的消费者 class,例如 Consumer<StateA>,以便他们的回调函数可以正确处理他们提供的类型。但是在下面的代码中,编译器会报错,因为在编译时,不会生成对 StateB consume 方法中的函数的调用。 consume 方法来自基础 class,它们必须被覆盖。

template <class T>
class Consumer : ConsumerBase
{
    public:
        Consumer(std::function<void(T&)> _callback){
            callback = _callback;
        }
        virtual void consume(StateA& state) { 
            callback(state);
        }
        virtual void consume(StateB& state) { 
            callback(state);
        }
    private:
        std::function<void(T&)> callback; 
};

基础Class:

class ConsumerBase
{
   public:
      virtual void consume(StateA& state) = 0;
      virtual void consume(StateB& state) = 0;
};

我怎样才能完成这项工作?

The consume methods come from a base class and they have to be overriden. [...] How can I make this work?

我想一个可能的解决方案是开发几个 consume_h() ("consume helper") 方法。

第一个完全匹配T(class的模板类型)调用回调函数

    void consume_h (T & state)
     { callback(state); }

第二个是什么都不做的模板版本

    template <typename U>
    void consume_h (U &)
     { }

现在你可以覆盖两个虚方法调用consume_h()

    virtual void consume (StateA & state)
     { consume_h(state); }

    virtual void consume (StateB & state)
     { consume_h(state); }

这样T对应的虚方法,调用调用回调的consume_h();另一个调用什么都不做的模板consume_h()

下面是一个完整的编译示例

#include <functional>

struct StateA { };
struct StateB { };

struct ConsumerBase
 {
   virtual void consume (StateA &) = 0;
   virtual void consume (StateB &) = 0;
 };

template <typename T>
class Consumer : ConsumerBase
{
    public:
        Consumer (std::function<void(T&)> cb0) : callback{cb0}
         { }

        void consume_h (T & state)
         { callback(state); }

        template <typename U>
        void consume_h (U &)
         { }

        virtual void consume (StateA & state)
         { consume_h(state); }

        virtual void consume (StateB & state)
         { consume_h(state); }

    private:
        std::function<void(T&)> callback; 
};

int main()
{
   Consumer<StateA>  csa{[](StateA &){ std::cout << "A" << std::endl; }};
   Consumer<StateB>  csb{[](StateB &){ std::cout << "B" << std::endl; }};

   StateA  sa;
   StateB  sb;

   csa.consume(sa);  // print A
   csb.consume(sb);  // print B
}