为什么 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
)。调用非模板版本,需要B
到A
的隐式版本;那么模板版本在重载决议中获胜。
您可以将 SFINAE 与 std::enable_if
和 std::is_base_of
一起应用,以在 T
被推导为 A
或其时从重载集中消除模板版本派生 类.
template<class T>
std::enable_if_t<!std::is_base_of_v<A, T>> fn2(T const &){
}
我做了一些测试并遇到了这种奇怪的行为。
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
)。调用非模板版本,需要B
到A
的隐式版本;那么模板版本在重载决议中获胜。
您可以将 SFINAE 与 std::enable_if
和 std::is_base_of
一起应用,以在 T
被推导为 A
或其时从重载集中消除模板版本派生 类.
template<class T>
std::enable_if_t<!std::is_base_of_v<A, T>> fn2(T const &){
}