为什么 C++ 编译器选择了错误的函数(模板)

Why C++ compiler chooses wrong function (templates)

我做了一些测试并遇到了这种奇怪的行为。

struct A{};

struct B : A{};

#include <iostream>

template<class T>
void fn2(T const &){
}

void fn2(A const &){
    std::cout << "Here\n";
}

template<class T>
void fn1(){
    T a;

    fn2(a);
}

int main(){
    fn1<B>();
}

我确实清理了代码。当 运行 时,我希望它打印 "here"。但是它调用 fn2().

的模板化版本

我也在godbolt中测试过。在那里我重写了函数 fn1()fn2(),所以它们 return int。那时,编译器做了正确的事情。

以下是我的编译方式:

$ gcc -Wall -Wextra -Wpedantic bug.cc  -lstdc++
$ ./a.out 
$ clang -Wall -Wextra -Wpedantic bug.cc  -lstdc++
$ ./a.out 
$ 

选择模板版本是因为它是完全匹配的(T 推断为 B)。调用非模板版本,需要BA的隐式版本;那么模板版本在重载决议中获胜。

您可以将 SFINAEstd::enable_ifstd::is_base_of 一起应用,以在 T 被推导为 A 或其时从重载集中消除模板版本派生 类.

template<class T>
std::enable_if_t<!std::is_base_of_v<A, T>> fn2(T const &){
}