I have a template class that implements a kind of dispatcher: the class processes "messages" which have "keys", and a part of the key is used to decide what "handler" to pass the message to. The user has to derive from the template class and provide the mapping from "keys" to the part of the key used for dispatch. I thought that a pure virtual function is a natural way to model that:
template<typename Key>
class Message {
public:
using key_type = Key;
/* more stuff which is irrelevant */
};
template<typename Message, typename KeyPortion, typename Handler>
class Dispatcher {
public:
virtual KeyPortion toHandlerKey(typename Message::key_type) = 0;
/* a bit more stuff which is irrelevant */
};
The user is forced to derive, and is forced to override the function. This is good.
Now, there are a couple situations where I could provide a default implementation for toHandlerKey
:
in the simplest case,
KeyPortion
is the same astypename Message::key_type
, so I could provide:virtual KeyPortion toHandlerKey(typename Message::key_type key) { return key; }
most of the time,
Message::key_type
is astd::tuple
containingKeyPortion
, so I could provide:virtual KeyPortion toHandlerKey(typename Message::key_type key) { return std::get<KeyPortion>(key); }
But I have no idea how to write that properly. I can't use enable_if
, because I'm not trying to overload anything. I can't provide a blanket implementation either, because then the user might forget to override it.
In summary, I want my template class to provide one of the three:
- a trivial virtual implementation for case (1) above;
- a trivial virtual implementation for case (2) above;
- a pure virtual function which will force the user to define their own implementation.
Is there a way to achieve that?