Search code examples
c++templatesoverload-resolution

Overload resolution, templates and inheritance


#include <iostream>

struct A {};
struct B : public A {};

template<typename T>
void foo(const T &x) { std::cout << "Called template" << std::endl; }

void foo(const A &a) { std::cout << "Called A" << std::endl; }

int main()
{
    foo(A());
    foo(B());
    return 0;
}

This prints:

Called A
Called template

I was under the impression that a suitable non-template function would always be chosen over a template function. Can someone explain to me the resolution steps that lead to this somewhat surprising result?


Solution

  • I was under the impression that a suitable non-template function would always be chosen over a template function.

    This only holds if the template and the non-template are equally good candidates. That's why the non-template is chosen for foo(A()).

    However, in the case of foo(B()), using the non-template requires a derived-to-base conversion. So the function template is strictly better, and hence it's chosen.

    The foo template instantiates into void foo(const B&). Consider what it would look like without templates:

    void foo(const B &x) { std::cout << "Called template" << std::endl; }
    
    void foo(const A &a) { std::cout << "Called A" << std::endl; }
    

    I believe you'll agree calling foo(B()) should unambiguously pick the first one. That's exactly why the template is chosen.