Reputation: 711
In the code below, I want a user to be able to create a consumer class with a specific type, eg Consumer<StateA>
so their callback function can correctly handle the type they give it. However in the code below, the compiler complains because at compile time, the call to the function in the StateB
consume method is not generated. The consume methods come from a base class and they have to be overriden.
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;
};
Base Class:
class ConsumerBase
{
public:
virtual void consume(StateA& state) = 0;
virtual void consume(StateB& state) = 0;
};
How can I make this work?
Upvotes: 0
Views: 253
Reputation: 66200
The consume methods come from a base class and they have to be overriden. [...] How can I make this work?
I suppose that a possible solution is develop a couple of consume_h()
("consume helper") methods.
The first one is an exact match for T
(the template type of the class) that call the callback function
void consume_h (T & state)
{ callback(state); }
The second one is a template version that do nothing
template <typename U>
void consume_h (U &)
{ }
Now you can override both virtual method calling consume_h()
virtual void consume (StateA & state)
{ consume_h(state); }
virtual void consume (StateB & state)
{ consume_h(state); }
This way the virtual method corresponding to T
, call the consume_h()
that call the callback; the other call the template consume_h()
that do nothing.
The following is a full compiling example
#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
}
Upvotes: 2