The output of the following code is TA, but I don't understand why.
#include <iostream>
#include <type_traits>
struct A {};
template<typename T>
void fun(T) {
std::cout << "T";
}
template<typename T>
void caller(T t) {
fun(A{});
fun(t);
}
void fun(A) {
std::cout << "A";
}
int main() {
caller(A{});
}
My understanding of templates tells me the following:
- just before the body of
mainis parsed, the only function "in place" is the non-template overload offun, the one printingA, because the templatesfunandcallerhave not been used and, in turn, instantiated; - only when the call to
calleris parsed, is the templatecallerinstantiated withT = A, which implies thatcallercallsfunwith objects of the same type in the two cases; - furthermore, since that type is
A, I'd say that the non-template overload offunis called in both cases.
However, the above is wrong, otherwise I would get AA (actually, also TT would surprise me less than TA).
I've also noted that moving the non-template overload before the definition of caller, the output becomes AA, so I can only make this conjecture:
- when the parser reads the line
fun(A{});thefuntemplate is instantiated withT = A, even though the templatecalleris not being instatiated yet; - then, when
caller(A{});is parsed,calleris instantiated; - only at this point the second call to
funin the body ofcallercan be interpreted as a call with an argument of typeA, but this time the non-templatefunis already known to the compiler, hence it's chosen as a better match.
I don't know if the above makes any sense, though.
More predictably, if if I use the following template specialization
template<>
void fun<A>(A) {
std::cout << "A";
}
instead of the non-template overload, then output is always AA, regardless of whether I put the specialization before or after caller's definition.