I want to be able to accept a Message& object which references either a Message1 or Message2 class. I want to be able to create a MessageWithData<Message1> or MessageWithData<Message2> based on the underlying type of the Message& object. For example, see below:
class Message {};
class Message1 : public Message {};
class Message2 : public Message {};
template<typename Message1or2>
class MessageWithData : public Message1or2 { public: int x, y; }
class Handler()
{
public:
void process(const Message& message, int x, int y)
{
// create object messageWithData whose type is
// either a MessageWithData<Message1> or a MessageWithData<Message2>
// based on message's type.. how do I do this?
//
messageWithData.dispatch(...)
}
};
The messageWithData class essentially contains methods inherited from Message which allow it to be dynamically double dispatched back to the handler based on its type. My best solution so far has been to keep the data separate from the message type, and pass it all the way through the dynamic dispatch chain, but I was hoping to come closer to the true idiom of dynamic double dispatch wherein the message type contains the variable data.
(The method I’m more or less following is from http://jogear.net/dynamic-double-dispatch-and-templates)
As has been mentioned, it is not possible to build your template as is.
I do not see any issue with passing additional parameters, though I would perhaps pack them into a single structure, for ease of manipulation.
Certainly I find it more idiomatic to use a supplementary
Dataparameter, rather than extending a class hierarchy to shoehorn all this into a pattern.It is an anti-pattern to try to make a design fit a pattern. The proper way is to adapt the pattern so that it fits the design.
That being said…
There are several alternatives to your solution. Inheritance seems weird, but without the whole design at hand it may be your best bet.
It has been mentioned already that you cannot freely mix compile-time and run-time polymorphisms. I usually use Shims to circumvent the issue:
The scheme is simple and allow you to benefit from the best of both worlds:
Messagebeing non-template mean that you can apply traditional OO strategiesMessageShim<T>being template mean that you can apply traditional Generic Programming strategiesOnce done, you should be able to get what you want, for better or worse.