假定下列功能模板:

#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)
{
};

其他提示

  

鉴于f的第二个参数是基本的派生类型

它转换为如,但它是派生*。第一模板函数不需要转换,并且第二要求之一,因此它选择所述第一

此选择第二:

f(v, static_cast<Base*>(&derived));

在一个方面说明,main返回int

除了有关 Koenig查找即由编译器(更多或更少的很好的实施尤其是老年人是很成问题),还有关于模板特

在专业化要求的类型,以完全匹配(不知道在std如何定义此,但是从我的经验[GCC,MSVC]派生类不会被匹配)。如果添加一个丑陋投地碱*,就应该像你打算选择添加另一种专业化的派生...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top