Based on overload resolution rules, the non-template version should be
preferred because the base class is of type Serializable
.
Not quite. [over.match.best]:
Given these definitions, a viable function F1
is defined to be a
better function than another viable function F2
if for all arguments
i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
- for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
- […]
F1
is not a function template specialization and F2
is a function template specialization […]
That means that only if the deduced specialization of the function template necessitates a conversion that isn't better than the conversion that the normal function necessitates, your rule applies.
And the binding of d
to Serializable&
is a worse conversion than the binding of d to MyData&
(which is the type of the parameter of the specialization), [over.ics.ref]:
When a parameter of reference type binds directly (8.5.3) to an
argument expression, the implicit conversion sequence is the identity
conversion, unless the argument expression has a type that is a
derived class of the parameter type, in which case the implicit
conversion sequence is a derived-to-base Conversion (13.3.3.1).
However, I expect SFINAE to kick in when there are errors in the
template version when it is instantiated for overload resolution
(because if the >> operator is not defined for a type, it should not
be considered).
SFINAE doesn't apply for the content of a function template. [temp.deduct]/8:
Only invalid types and expressions in the immediate context of the
function type and its template parameter types can result in a
deduction failure.
Hence the deduced specialization of the function template is indeed chosen, and causes a compiler error while instantiating its definition.