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
main
is parsed, the only function "in place" is the non-template overload offun
, the one printingA
, because the templatesfun
andcaller
have not been used and, in turn, instantiated; - only when the call to
caller
is parsed, is the templatecaller
instantiated withT = A
, which implies thatcaller
callsfun
with objects of the same type in the two cases; - furthermore, since that type is
A
, I'd say that the non-template overload offun
is 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{});
thefun
template is instantiated withT = A
, even though the templatecaller
is not being instatiated yet; - then, when
caller(A{});
is parsed,caller
is instantiated; - only at this point the second call to
fun
in the body ofcaller
can be interpreted as a call with an argument of typeA
, but this time the non-templatefun
is 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.