Reputation: 10539
I did some tests and encountered this strange behavior.
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>();
}
I did clean up the code. When run, I expect it prints "here". However it call templated version of fn2()
.
I did test in godbolt as well. There I rewrited the function fn1()
and fn2()
, so they return int
. At that point, compiler did the right thing.
Here is how I compile:
$ gcc -Wall -Wextra -Wpedantic bug.cc -lstdc++
$ ./a.out
$ clang -Wall -Wextra -Wpedantic bug.cc -lstdc++
$ ./a.out
$
Upvotes: 2
Views: 290
Reputation: 172864
The template version is selected because it's an exact match (with T
deduced as B
). For the non-template version to be called, the implicit version from B
to A
is required; then the template version wins in overload resolution.
You can apply SFINAE with std::enable_if
and std::is_base_of
to eliminate the template version from the overload set when T
is deduced as A
or its derived classes.
template<class T>
std::enable_if_t<!std::is_base_of_v<A, T>> fn2(T const &){
}
Upvotes: 4