I have a base class which implements the following:
struct Consumer
{
template <typename T>
void callback(T msg) { /*null implementation */ }
};
I then have a class implement this:
struct Client : public Consumer
{
void callback(Msg1 msg);
void callback(Msg2 msg);
void callback(Msg3 msg);
};
The issue is I have a container of Client objects treated as Consumer* and I can’t think of a way to get these Consumer objects to call the derived functions. My intended functionality is to have multiple Clients each of which implement an overloaded function for each Msg class that means something to them and the rest of the calls simply call the null implementation in the base class
Any thoughts how I can get the derived class to be called? Right now I need to implement every overloaded function in Consumer and mark them as virtual.
Cheers,
Graeme
If you really don’t want to use virtual functions (this seems to be a perfect use case for them actually, but I don’t know about your message classes), you can use the CRTP:
The problem, of course, is that you cannot store
Consumerobjects in a container any more. Since everything is compile time, the actual type of the client must be stored alongside the consumer object for the compiler to call the right callback function. Virtual functions allow you to wait until runtime for this…Is there a reason not to have
Msgclasses polymorphic and use standard virtual functions (other than “I have to rewrite all the code and I cannot”) ?EDIT If your concern is about message classes, why not use something like that, assuming message classes implement a
DoSomethingmember function: (this technique is known as Type Erasure)You can customize the behavior of
newImplto get what you want (eg. default actions if there is noDoSomethingmember function in the message class, specialization for some message classes or anything else). This way, you implementMsgclasses like you would have done with your template solution, and you have a unique facade that you can pass to the virtual functions in your client classes.If the Message classes are going to be very different, and client classes may react differently to them, and you are going to have a lot of message classes, this begins to smell. Or perhaps you have a candidate for the ugly and scary Visitor pattern.