Методы потребления происходят из базового класса и должны быть переопределены.[...] Как я могу заставить эту работу работать?
Я полагаю, что возможное решение - это разработать пару consume_h()
("потребление помощника") методов.
первый - точное соответствие для T
(тип шаблона класса), который вызывает функцию обратного вызова
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
}