为什么编译器选择这个模板函数而不是重载的非模板函数?
Why is the compiler choosing this template function over an overloaded non-template function?
使用vc++ 2010,给出如下:
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
来实现这一点,但为什么这是必要的?
我希望对所有不是从Base
派生的类型(内置类型等)调用模板函数,但我希望对从Base
派生的类型调用非模板重载,而不需要客户端显式强制转换。我也尝试过使重载成为模板的专门化,但在这种情况下会发生相同的行为。得到我想要的东西的惯用方法是什么?
在所有条件相同的情况下,非模板函数优于函数模板。然而,在您的场景中,并非所有事情都是相等的:(A)与T = Derived
完全匹配,但是(B)需要将参数从派生到基的转换。
您可以通过使用SFINAE(替换失败不是错误)来解决特定情况下的这个问题,以防止(A)被实例化为从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)
{
}
选择模板版本是因为当使用类型为Derived
的参数调用时,它比重载版本更匹配。您可以使用SFINAE从重载解析中删除模板版本,以便在使用Base
或Derived
类型的参数调用时选择其他版本。
#include <type_traits>
#include <iostream>
class Base { };
class Derived : public Base { };
template<class T>
typename std::enable_if<
std::is_base_of<Base, T>::value == false
>::type
foo(T&)
{
std::cout << "template foo" << std::endl;
}
void foo(Base&)
{
std::cout << "non-template foo" << std::endl;
}
int main()
{
Derived d;
Base b;
foo( d );
foo( b );
}
相关文章:
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- c++:可变模板和函数重载
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 解决模板成员函数重载
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 推断模板化函数中的函数重载
- C++复制函数重载导致"must be a nonstatic member function"错误
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- 可变参数泛型 lambda 和函数重载
- C++中的函数重载和继承
- 当有右值构造函数可用时,为什么从右值调用类引用构造函数重载?
- C/C++ 可变参数宏函数重载
- 将基类的成员函数重载到其他派生类C++
- C++ 函数重载匹配
- C++函数重载,具体步骤是什么
- C++:使用 param pack 显式调用函数重载
- 隐式生成的函数重载用于右值参数?
- 使用函数重载输入运算符
- 运算符重载函数上的函数重载