Let's say I have something like this:
class Outer
{
public:
void send(A a) { ... }
template <typename MessageType>
void send(MessageType message) { innerBase->doSend(message); }
private:
InnerBase* innerBase;
};
where InnerBase being a polymorphic base class:
class InnerBase
{
public:
virtual void doSend(B b) = 0;
virtual void doSend(C c) = 0;
virtual void doSend(D d) = 0;
};
class InnerDerived : public InnerBase
{
public:
virtual void doSend(B b) override { ... }
virtual void doSend(C c) override { ... }
virtual void doSend(D d) override { ... }
};
So far so good, and if I want to add overloads I just need to add them to InnerBase and InnerDerived.
At some point, it turns out I need to make the outer class customizable too, so I'd like to be able to write something like this :
class OuterBase
{
public:
template <typename MessageType>
virtual void send(MessageType message) = 0;
};
class OuterDerived : public OuterBase
{
public:
void send(A a) { ... }
template <typename MessageType>
virtual void send(MessageType message) override { innerBase->send(message); }
private:
InnerBase* innerBase;
};
But that's not allowed by the standard, which forbids templated virtual member functions. Instead I'm forced to write all the overloads one by one like this :
class OuterBase
{
public:
virtual void send(A a) = 0;
virtual void send(B b) = 0;
virtual void send(C c) = 0;
virtual void send(D d) = 0;
};
class OuterDerived : public OuterBase
{
public:
virtual void send(A a) override { ... }
virtual void send(B b) override { innerBase->doSend(b); }
virtual void send(C c) override { innerBase->doSend(c); }
virtual void send(D d) override { innerBase->doSend(d); }
private:
InnerBase* innerBase;
};
That's a lot of boilerplate code, and that means that if I ever want to add another overload I need to modify 4 classes instead of just 2 (and twice as many files). Assuming I need more than one level of indirection, this could easily go up to 6, 8, etc, making the addition of new overloads totally impractical.
Am I doing this wrong? Is there a cleaner way to do this?
The only alternative I can think of would be to leak the innerBase pointer to the base class so that it can call doSend() directly, which would allow to keep send() templated, but that both breaks encapsulation and prevents OuterDerived from adding its own send() overloads
as well as from adding its own logic around the calls to doSend()...