C++:重载不会选择预期的方法

ATe*_*emp 0 c++ inheritance templates overloading

我有以下代码:

#include <iostream>
#include <vector>
using namespace std;

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

template <typename T>
void foo(const T& obj) { cerr << "Generic case"<< endl;}

void foo(const A& a) {
    cerr << "Specific case" << endl;
}

int main() {
    vector<int> v;
    foo(v);
    B b;
    foo(b);
    A a;
    foo(a);
}
Run Code Online (Sandbox Code Playgroud)

输出是

  • 一般情况
  • 一般情况
  • 具体情况

为什么foo(const A& a)没有为B对象选择它?

奇怪的是,如果我删除了模板化方法并且只是具有以下内容:

#include <iostream>
#include <vector>

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

//template <typename T>
//void foo(const T& obj) { cerr << "Generic case"<< endl;}

void foo(const A& a) {
    cerr << "Specific case" << endl;
}

int main() {
    B b;
    foo(b);
    A a;
    foo(a);
}
Run Code Online (Sandbox Code Playgroud)

代码编译,输出为:

Specific case
Specific case
Run Code Online (Sandbox Code Playgroud)

为什么模板化方法的存在会产生这样的差异?

编辑:如何在存在模板化方法的情况下强制编译器为从A派生的类选择自由方法?

pmr*_*pmr 11

foo(const B&)模板实例化产生的调用不需要转换,因此它是更好的匹配.

当编译器看到函数调用时,必须实例化每个基函数模板,并将其与每个正常函数一起包含在重载集中.之后执行重载决策.还有SFINAE,它允许实例化函数模板导致错误(这样的函数不会被添加到过载集中).当然,事情并非如此简单,但它应该给出一般情况.

关于你的编辑:只有一种方法可以调用.还有什么可以作为输出?