为什么编译器不要选择我的函数模板重载下面的例子吗?
-
21-09-2019 - |
题
假定下列功能模板:
#include <vector>
#include <utility>
struct Base { };
struct Derived : Base { };
// #1
template <typename T1, typename T2>
void f(const T1& a, const T2& b)
{
};
// #2
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};
为什么是它下面的代码总是调用过载#1,而不是过载#2?
int main()
{
std::vector<std::pair<int, int> > v;
Derived derived;
f(100, 200); // clearly calls overload #1
f(v, &derived); // always calls overload #1
return 0;
}
鉴于f
的第二个参数的Base
派生类型,我希望编译器会选择过载#2,因为它比在过载#1中的一般类型的更好匹配。
是否有作为main
功能显示我可以使用重写这些功能,使得用户可以编写代码的任何技术(即参数类型的利用编译器扣)?
解决方案
您可以做到这一点:
f(v, static_cast<Base*>(&derived));
或者使用SFINAE以移除第一功能为选择候选:
// Install boost library and add these headers:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
// #1 - change it to look like this (note the keyword void changed positions)
template <typename T1, typename T2>
typename boost::disable_if<
typename boost::is_convertible<T2, Base*>, void>::type
f(const T1& a, const T2& b)
{
};
// #2 - this one can stay the same
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};
不隶属于 StackOverflow