为什么编译器选择此模板函数而不是重载的非模板函数? [英] Why is the compiler choosing this template function over an overloaded non-template function?
问题描述
使用VC ++ 2010,具体如下:
Using VC++ 2010, given the following:
class Base { };
class Derived : public Base { };
template<class T> void foo(T& t); // A
void foo(Base& base); // B
Derived d;
foo(d); // calls A
foo(static_cast<Base&>(d)); // calls B
我想在上面叫"B".我可以通过强制转换为Base
来实现这一点,但是为什么这样做是必需的?
I would like "B" to be called above. I can achieve this with a cast to Base
, but why is this necessary?
我希望为不是从Base
派生的所有类型(内置类型等)调用模板函数,但是我希望为从Base
派生的类型调用非模板重载,而没有要求客户明确投放.我还尝试使重载成为模板的特殊化,但是在这种情况下会发生相同的行为.获得我要找的东西的惯用方式是什么?
I want the template function to be called for all types not derived from Base
(built-in types, etc.), but I want the non-template overload to be called for types derived from Base
, without requiring the client to explicitly cast. I also tried making the overload a specialization of the template, but the same behavior occurs in that case. What is the idiomatic way to get what I'm looking for?
推荐答案
在所有条件都相同的情况下,非模板函数优于函数模板.但是,在您的情况下,所有条件都不相等:(A)与T = Derived
完全匹配,但是(B)需要参数的派生到基数转换.
All things being equal, nontemplate functions are preferred over function templates. However, in your scenario, all things are not equal: (A) is an exact match with T = Derived
, but (B) requires a derived-to-base conversion of the argument.
您可以通过使用SFINAE(替代失败不是错误)来解决特定情况(如这种情况)的情况,以防止使用从Base
派生的类型实例化(A):
You can work around this for specific cases (like this one) by using SFINAE (substitution failure is not an error) to prevent (A) from being instantiated with a type that is derived from Base
:
#include <type_traits>
#include <utility>
template <typename T>
typename std::enable_if<
!std::is_base_of<Base, T>::value
>::type foo(T& x)
{
}
void foo(Base& x)
{
}
这篇关于为什么编译器选择此模板函数而不是重载的非模板函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!