在“C ++模板 - 完整指南”一书的2.4 Overloading Function Templates
部分中,您将找到以下示例:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
return a < b ? b : a;
}
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c);
}
int main()
{
::max(7, 42); // calls the nontemplate for two ints (1)
}
然而,在附录B的B.2简化重载决议中,作者声明:
请注意,在模板参数扣除之后发生重载解析,...(2)
根据(2)
,::max(7,42)
应通过参数扣除来调用max<int>
。
答案 0 :(得分:4)
如果函数既完全匹配又包含cv
限定符,编译器在重载解析时会更喜欢非模板函数。
因此,非模板将在此处被选中,即使模板化函数基本上相同。
编辑:
在标准草案N3485中我发现了这个:
13.3.3最佳可行功能[over.match.best]
鉴于这些定义,如果对于所有参数i,可行函数F1被定义为更好函数而不是另一个可行函数F2,ICSi(F1)不是比ICSi更差的转换序列(F2) ),然后
...
- F1是非模板函数,F2是函数模板特化,或者,如果没有,
- F1和F2是功能模板特化,根据14.5.6.2中描述的偏序规则,F1的功能模板比F2的模板更专业。
...
答案 1 :(得分:3)
根据
(2)
,::max(7,42)
应通过参数扣除来调用max<int>
。
没有。考虑一下,要进行重载解析(也就是说,选择最佳匹配),编译器首先需要知道所有可用的重载并能够比较它们。注意函数模板本身不是一个有效的函数,首先需要实例化来创建一个真正的函数。
这意味着首先,编译器会查找名为max
的所有函数模板,为每个函数模板尝试模板参数推导,然后对实例化函数和非模板函数进行重载解析。< / p>
这是功能的可视化(为了简洁省略了cv限定符):
int max(int, int);
template<class Arg> Arg max(Arg, Arg);
template<class Arg> Arg max(Arg, Arg, Arg);
让我们来看看::max(7, 42)
。
首先,编译器发现有三个候选函数。但是,它不能只比较max
与其他两个的第一次重载 - 这就像比较苹果和橙子一样。相反,它首先需要从功能模板蓝图中“消除”一个真实的功能。在我们的例子中,这通过模板参数推导发生:
int max(int, int); // originally non-template
int max(int, int); // originally template
int max(int, int, int); // not enough arguments, invalid
由于参数/参数计数不匹配导致第三次重载被抛出,我们只有两次。从重载分辨率的角度来看,两者都是平等的 - 但是等等!现在有一个规则步骤:
§13.3.3 [over.match.best] p1
[......]鉴于这些定义,如果[...]:
,可行函数F1
被定义为比另一个可行函数F2
更好的函数。
F1
是非模板函数,F2
是函数模板特化,
答案 2 :(得分:2)
模板参数扣除后,重载决策发生在
之间1) inline int const& max (int const& a, int const& b);
和
2) template <>
inline int const& max (int const& a, int const& b)
在这种情况下,按照C ++标准13.3.3 par中的规定调用1)。 1(Draft n3092)。
Msdn也明确表示:
如果nontemplate函数与模板函数同样匹配,则选择nontemplate函数
http://msdn.microsoft.com/en-us/library/s016dfe8%28v=vs.80%29.aspx
答案 3 :(得分:1)
C ++ 11标准中的每段13.3.3 / 1(在重载解析的上下文中为“最佳可行功能”):
如下定义ICSi(F):
- 如果F是静态成员函数,则定义ICS1(F)使得ICS1(F)既不好也不差 对于任何函数G,ICS1(G),对称地,ICS1(G)既不比ICS1(F)132更好也不差; 否则,
- 让ICSi(F)表示隐式转换序列,它将列表中的第i个参数转换为 有效函数F的第i个参数的类型.13.3.3.1定义了隐式转换序列和 13.3.3.2定义了一个隐式转换序列对于更好的转换序列意味着什么 或者转换顺序比另一个更差。
鉴于这些定义,一个可行的函数F1被定义为比另一个可行函数更好的函数 对于所有参数i,如果为F2,则ICSi(F1)的转换序列不比ICSi(F2)差,然后
- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,
- 上下文是用户定义转换的初始化(见8.5,13.3.1.5和13.3.1.6)和 从返回类型F1到目标类型的标准转换序列(即,类型的 正在初始化的实体)是比标准转换序列更好的转换序列 F2的返回类型到目标类型。 [...]
- F1是非模板功能,F2是功能模板专业化,或者,如果不是,
- F1和F2是功能模板专精,F1的功能模板更专业 根据14.5.6.2中描述的偏序规则,比F2的模板。
这意味着在重载解析的上下文中,当通过实例化函数模板生成的函数(因此,在类型推导之后)与非模板函数同样良好匹配时,非模板函数是首选。 / p>