为什么模板重载比简单转换更匹配?
Why is template overload a better match than a simple conversion?
#include <iostream>
using namespace std;
template<typename T>
void func(T t) { std::cout << "matched template\n"; }
void func(long x) { std::cout << "matched long\n"; }
int main()
{
func(0);
}
输出:
matched template
在其他情况下,当重载解析可能不明确时,首选非模板函数,为什么这个不同?
我认为(但不是绝对确定,即不知道标准中的确切引用,但会尝试查找)如果参数与非模板的类型不完全匹配,那么模板将启动。或者,换句话说,转换次数趋于最小化。例如,在
f(long)
对比
template <typename T>
f(T)
f(long)
需要转换(从 0
,例如 int
,到 long
),而模板不需要(当然)转换。
经过@T.C 的一些挖掘和帮助,标准的相关部分是 Sec。 13.3.3,[over.match.best]。这是一个相当长的技术部分,但基本上是说带有 Identity
转换的函数优于非 Identity
转换。
隐式转换可能会带来开销,并且可能对程序员来说是意想不到的,所以对我来说,标准选择不涉及转换的选项似乎是合乎逻辑的。
§13.3.3 [over.match.best]/p1-2:
1 Define ICSi(F)
as follows:
- (1.1) [inapplicable bullet omitted]
- (1.2) let
ICSi(F)
denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of
viable function F
. 13.3.3.1 defines the implicit conversion
sequences and 13.3.3.2 defines what it means for one implicit
conversion sequence to be a better conversion sequence or worse
conversion sequence than another.
Given these definitions, a viable function F1
is defined to be a
better function than another viable function F2
if for all arguments
i
, ICSi(F1)
is not a worse conversion sequence than ICSi(F2)
,
and then
(1.3) for some argument j
, ICSj(F1)
is a better conversion sequence than ICSj(F2)
, or, if not that,
[several inapplicable bullets omitted]
- (1.6)
F1
is not a function template specialization and F2
is a function template specialization, or, if not that,
- [inapplicable bullet omitted]
2 If there is exactly one viable function that is a better function
than all other viable functions, then it is the one selected by
overload resolution; otherwise the call is ill-formed.
§13.3.3.2 [over.ics.rank],项目符号 3.2:
- (3.2) Standard conversion sequence
S1
is a better conversion sequence than standard conversion sequence S2
if
- (3.2.1)
S1
is a proper subsequence of S2
(comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any
Lvalue Transformation; the identity conversion sequence is considered
to be a subsequence of any non-identity conversion sequence)
令 F1 = func<int>(int)
,F2 = func(long)
,只有一个参数,类型为 int
。所以ICS1(F1)
就是身份转换; ICS1(F2)
是从int
到long
的整数转换;因此,根据 [over.ics.rank]/3.2.1 ICS1(F1)
是比 ICS1(F2)
更好的转换序列(因此根据定义并不比 ICS1(F2)
差)。因此,根据 [over.match.best] 中的项目符号 1.3,F1 优于 F2。 template/non-template 决胜局,在项目符号 1.6 中,根本没有发挥作用。
#include <iostream>
using namespace std;
template<typename T>
void func(T t) { std::cout << "matched template\n"; }
void func(long x) { std::cout << "matched long\n"; }
int main()
{
func(0);
}
输出:
matched template
在其他情况下,当重载解析可能不明确时,首选非模板函数,为什么这个不同?
我认为(但不是绝对确定,即不知道标准中的确切引用,但会尝试查找)如果参数与非模板的类型不完全匹配,那么模板将启动。或者,换句话说,转换次数趋于最小化。例如,在
f(long)
对比
template <typename T>
f(T)
f(long)
需要转换(从 0
,例如 int
,到 long
),而模板不需要(当然)转换。
经过@T.C 的一些挖掘和帮助,标准的相关部分是 Sec。 13.3.3,[over.match.best]。这是一个相当长的技术部分,但基本上是说带有 Identity
转换的函数优于非 Identity
转换。
隐式转换可能会带来开销,并且可能对程序员来说是意想不到的,所以对我来说,标准选择不涉及转换的选项似乎是合乎逻辑的。
§13.3.3 [over.match.best]/p1-2:
1 Define
ICSi(F)
as follows:
- (1.1) [inapplicable bullet omitted]
- (1.2) let
ICSi(F)
denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable functionF
. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.Given these definitions, a viable function
F1
is defined to be a better function than another viable functionF2
if for all argumentsi
,ICSi(F1)
is not a worse conversion sequence thanICSi(F2)
, and then
(1.3) for some argument
j
,ICSj(F1)
is a better conversion sequence thanICSj(F2)
, or, if not that,[several inapplicable bullets omitted]
- (1.6)
F1
is not a function template specialization andF2
is a function template specialization, or, if not that,- [inapplicable bullet omitted]
2 If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed.
§13.3.3.2 [over.ics.rank],项目符号 3.2:
- (3.2) Standard conversion sequence
S1
is a better conversion sequence than standard conversion sequenceS2
if
- (3.2.1)
S1
is a proper subsequence ofS2
(comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence)
令 F1 = func<int>(int)
,F2 = func(long)
,只有一个参数,类型为 int
。所以ICS1(F1)
就是身份转换; ICS1(F2)
是从int
到long
的整数转换;因此,根据 [over.ics.rank]/3.2.1 ICS1(F1)
是比 ICS1(F2)
更好的转换序列(因此根据定义并不比 ICS1(F2)
差)。因此,根据 [over.match.best] 中的项目符号 1.3,F1 优于 F2。 template/non-template 决胜局,在项目符号 1.6 中,根本没有发挥作用。