If I have
template<class T>
TalkyBuffer& operator<<(T const &object) { // Template
...
}
TalkyBuffer& operator<<(TalkySerialisable const &object); // Override
and a class
class A : public TalkySerialisable {
...}
Then if I perform
TalkyBuffer b;
A test;
b << test;
Then gcc is calling the Template function rather than the Override function
However if I specifically define an override
TalkyBuffer& operator<<(A const &object); // Override without polymorphism
Then gcc picks that one. Is there a practical way to override a templated function with an abstract class?
I read this but it doesn't shed light onto what happens when you throw polymorphism into the mix: http://www.gotw.ca/publications/mill17.htm Also I couldn't find a solution here but perhaps I'm using the wrong terms.
When defining the function TalkyBuffer& operator<<(TalkySerialisable const &object);
You are not overriding. You are overloading the tmeplated function.
But, when the complier sees b << test;
, it searches for an operator that wants an A
. It has one, it's the templated function that requires no automatic cast. This is the best choice.
The overloaded function requires an automatic cast (from A to TalkySerialisable) on the parameters to fit the declaration, and is not the best choice.
I think it's possible to use a simple function
based solution, reusing function overload for derivation.
struct specialized {};
struct generic {};
template <class T>
TalkyBuffer& serialize(TalkyBuffer& buffer, T const& object, generic) {
...
}
generic dispatch(...) {} // always picked up last in overload resolution
template <class T>
TalkyBuffer& TalkyBuffer::operator<<(T const& object) { // Template
return serialize(*this, object, dispatch(object));
}
Now, let's implement your custom class:
TalkyBuffer& serialize(TalkyBuffer& buffer,
TalkySerialisable const& object,
specialized);
specialized dispatch(TalkySerialisable const&) {}
And create a derived one:
class A: public TalkySerialisable {};
So, what happens ?
TalkyBuffer::operator<<(T const&)
will be picked upserialize
, it will first compute the result of dispatch
dispatch
, dispatch(TalkySerializable const&)
is a better match than dispath(...)
, thus the return type is specialized
serialize
cannot be used (there is no conversion from specialized
to generic
), so inheritance kicks inIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With