Interaction between templates and overloads

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); // the same output if I do `fun(std::move(t))`, so the value category seems not relevant here
}

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 of fun, the one printing A, because the templates fun and caller have not been used and, in turn, instantiated;
  • only when the call to caller is parsed, is the template caller instantiated with T = A, which implies that caller calls fun with objects of the same type in the two cases;
  • furthermore, since that type is A, I’d say that the non-template overload of fun 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{}); the fun template is instantiated with T = A, even though the template caller 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 of caller can be interpreted as a call with an argument of type A, but this time the non-template fun 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.

Source: Windows Questions C++

LEAVE A COMMENT