基类的模板函数重载 [英] Template function overload for base class
问题描述
如何强制编译器为基类拾取模板函数重载?
下面是一个说明问题的示例
#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< 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;
}
它产生输出
通用f
A
的重载通用f
b $ b
为什么在第三种情况下编译器不能拾取 f(const A&)
? UPD :好的,这个很清楚 void f< B> (const B&)
比 void f(const A&)
好,但我仍然在寻找第二个问题的答案。 / p>
是否可以强制它不将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 \\\
;
}
如果不能使用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 \\\
;
}
void f(A const& true_type)
{
std :: cout< Overload for A\\\
;
}
template< class T>
void call_f(const T& t)
{
f(t,A_is_base_of(& t));
}
How do I force compiler to pick up a template function overload for a base class?
Here is an example that illustrates the question
#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;
}
It produces the output
Generic f
Overload for A
Generic f
Why doesn't the compiler pick up f (const A&)
in the 3rd case? UPD: OK, this one is clear void f<B> (const B&)
is better than void f (const A&)
, but I'm still looking for answer to the 2nd question.
And is it possible to force it to do so without casting B to A?
Using call_f(B())
results in a call to `f() which is best matched by the template version. For the non-template version a conversion is required. As a result, the template is chosen. If the template and the non-template would be equally good options, the non-template would be preferred.
If you want to the non-template to be called, you'll need to make the template a non-option. for example, the template could be implemented like
#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";
}
If C++11 can't be used you could either implement a version of std::is_base_of<...>
, use a version from Boost or use a simple dispatch:
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));
}
这篇关于基类的模板函数重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!