我如何强制编译器为基类选择模板函数重载?
举个例子说明问题
#include <iostream>
class A
{};
class B : public A
{};
template <class T>
void f (const T& t)
{
std::cout << "Generic f" << std::endl;
}
void f (const A& a)
{
std::cout << "Overload for A" << std::endl;
}
template <class T>
void call_f (const T& t)
{
f (t);
}
int main()
{
call_f (10);
call_f (A());
call_f (B());
return 0;
}
它产生输出
Generic f
Overload for A
Generic f
为什么编译器不接收 f (const A&)
在第三种情况下? UPD:好的,这个很清楚void f<B> (const B&)
优于void f (const A&)
,但我仍在寻找第二个问题的答案。
是否有可能强制它这样做而不将 B 转换为 A?
使用 call_f(B())
导致调用与模板版本最匹配的`f()。对于非模板版本,需要进行转换。结果,选择了模板。如果模板和非模板是同样好的选择,那么非模板将是首选。
如果要调用非模板,则需要将模板设为非选项。例如,模板可以这样实现
#include <type_traits>
template <class T>
typename std::enable_if<!std::is_base_of<A, T>::value>::type f(T const&)
{
std::cout << "Generic f\n";
}
如果不能使用 C++11,您可以实现 std::is_base_of<...>
的一个版本,使用来自 Boost 的版本或者使用简单的调度:
struct true_type {};
struct false_type {};
true_type A_is_base_of(A const*) { return true_type(); }
false_type A_is_base_of(void const*) { return false_type(); }
template <class T>
void f (T const&, false_type)
{
std::cout << "Generic f\n";
}
void f (A const&, true_type)
{
std::cout << "Overload for A\n";
}
template <class T>
void call_f (const T& t)
{
f (t, A_is_base_of(&t));
}