In this case I believe gcc is right. You are asking the compiler to perform type deduction for you, and the problem is that the given argument of type DerivedFunction
is not a FunctionImplementation<TDerived>
directly, so a conversion has to be performed. At this point the list of conversions includes FunctionImplementation<BaseFunction>
(through BaseFunction
) and FunctionImplementation<DerivedFunction>
(directly). There is no ordering among those two choices, so the compiler bails out with an ambiguity.
The standard treats this in §14.8.2.1 [temp.deduct.call]/4,5
(paragraph 4) In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:
[...]
If P is a class and P has the form simple-template-id, then the transformed A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class pointed to by the deduced A.
(paragraph 5) These alternatives are considered only if type deduction would otherwise fail. If they yield more than one possible deduced A, the type deduction fails.
In the 4th paragraph it allows type deduction to pick a base of the argument type, in this case there are 2 such bases. The 5th paragraph determines that if the application of the previous rule yields more than one result, then type deduction fails.