了解整个功能模板超载分辨率的过程
我发现超负荷分辨率过程是我在C ++中学到的更为复杂的过程,因此请记住,这个话题对我来说很难轻松理解,因此请耐心等待。
我在这里有两个示例,我试图单独解析每个示例,并了解编译器实际上从呼叫开始到过载模板的实际要做的事情,直到确定哪个过载是最佳的可行。
第一个示例#1
template <class T> void f(const T&); // F1: reference to const T
template <class T> void f(const T*); // F2: pointer to const T
f((int*)0);
// matching F1:
// deduction: P = const T&, A = int* --> const T& = int* --> T = int*
// instantiates: void f(int *const&); A = int*, P = int *const&
// S1 conversion: int* --> int* const& (identity conversion?)
// matching F2:
// P = const T*, A = int* --> const T* = int*; T = int;
// instantaies: void f(const int*); A = int*, P = const int*;
// S2 conversion: int* --> const int* (qualification conversion)
标准转换序列
s1
是一个更好的转换序列 标准转换序列S2
如果
- (3.2.1)S1是适当的子序列
s2
(比较规范形式的转换序列 由12.2.4.2.2定义,不包括任何LVALUE转换;这 身份转换序列被认为是任何的子序列 非身份转换序列)- [..]
s1
是s2
的适当子序列:这是身份转换是资格转换的正确子序列,因为身份转换顺序被认为是成为任何非身份转换序列的子序列。
和per [over.match.best.general]/2 :
给定这些定义,可行的函数
f1
被定义为 与其他可行函数更好的功能f2
如果所有参数 i,ICSI(F1)
不比ICSI(F2)
更差的转换序列,然后是
- (2.1) - 对于某些参数
J
,ICSJ(f1)
是一个更好的转换序列>- [..]
更好的转换 f1
(这是身份转换)“ 不好”,比f2
的所有参数的隐式转换(这是资格转换)和至少有一个参数的f1
其隐式转换优于f2
参数的相应隐式转换。那么可行的函数f1
是比可行函数f2
更好的功能。因此,f1
的专业化是通过过载分辨率为给定呼叫选择的。
我的问题:
- 我是否正确解析了整个过程?
- 编译器此时是否需要执行部分顺序?如果是,为什么?即使我们从IC中知道
f1
是最好的可行候选人?
第二个示例#2
template <class T> void f(const T&); // F1: reference to const T
template <class T> void f(T*); // F2: pointer to T
f((int*)0);
// matching F1:
// deduction: P = const T&, A = int* --> const T& = int* --> T = int*
// instantiates: void f(int *const&); A = int*, P = int *const&
// S1 conversion: int* --> int* const& (identity conversion)
// matching F2:
// deduction: P = T*, A = int* --> T* = int*; T = int
// instantaies: void f(int*); A = int*, P = int*
// S2 conversion: int* --> int* (identity conversion)
在[over.ics.rank] /3/3.2
中都没有规则。这是s1
和s2
是身份转换。
然后,编译器将转到下一步以检查 [[ over.match.best.general]/2 。的确,ICSI(F1)
并不比ICSI(F2)
更糟糕,但是
2.1
bullet不满足,因为iCSI (f1)
不是ICSI(F2)
更好的转换序列。 f1
参数的隐式转换序列实际上与f2
的参数相同(即不糟糕)。
编译器不断检查[over.match.best.general]/2中的规则,直到击中子弹 2.5 说:
- [..]
- (2.5) - f1和f2是功能模板专业化, F1的功能模板比F2的模板更专业 根据部分订购规则[..]
我不会经历部分订购的整个过程,而是会总结一切。
调整功能签名:
void f(T); // Tem1
void f(T*); // Tem2
转换功能签名:
void f(U1); // Tra1
void f(U2*); // Tra2
匹配tem1
针对tran2
:
void f(T); // Tem1
void f(U2*); // Tra2
// T = U2* - OK: T can be deduced from U2*
匹配tem2
针对tran1
:
void f(T*); // Tem2
void f(U1); // Tra1
// T* = U1 - error: T cannot be deduced
SO模板由 tran1
: tra2
比tran1
引用的模板更专业:f2
比f1
。因此,f2
的专业化将由给定呼叫的过载分辨率选择。
我的问题:
- 我是否正确解析了整个过程?
- 我认为(可能是不正确的)是,在模板参数扣除后,编译器为两个过载以匹配ICS过程的P/A对的专业化。现在,编译器是否再次为更专业的模板生成专业化?
相信我,在发布此问题之前,我搜索了一个涵盖整个过程的问题。我需要知道的是,我是否在想正确,以及我提供的所有报价是否都应用于示例。
抱歉花了很长时间,并提前感谢。
I found out that the overload resolution process is the more complicated I have ever learned in C++, Therefore, bear in mind that this topic is relatively difficult for me to understand easily, so be patient with me.
I have two examples here, and I tried to parse each example separately and understand what actually the compiler is doing starting from the call to the overloaded template until determining which overload is the best viable.
First Example #1
template <class T> void f(const T&); // F1: reference to const T
template <class T> void f(const T*); // F2: pointer to const T
f((int*)0);
// matching F1:
// deduction: P = const T&, A = int* --> const T& = int* --> T = int*
// instantiates: void f(int *const&); A = int*, P = int *const&
// S1 conversion: int* --> int* const& (identity conversion?)
// matching F2:
// P = const T*, A = int* --> const T* = int*; T = int;
// instantaies: void f(const int*); A = int*, P = const int*;
// S2 conversion: int* --> const int* (qualification conversion)
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 12.2.4.2.2, excluding any Lvalue Transformation; the
identity conversion sequence is considered to be a subsequence of any
non-identity conversion sequence)- [..]
S1
is s a proper subsequence of S2
: that's identity conversion is a proper subsequence of qualification conversion because the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence.
and per [over.match.best.general]/2:
Given these definitions, a viable function
F1
is defined to be a
better function than another viable functionF2
if for all arguments
i,ICSi(F1)
is not a worse conversion sequence thanICSi(F2)
, and then
- (2.1) — for some argument
j
,ICSj(F1)
is a better conversion sequence thanICSj(F2)
- [..]
Here, the implicit conversions for all arguments of F1
(which is identity conversion) are "not worse" than the implicit conversions for all arguments of F2
(which is qualification conversion), and there is at least one argument of F1
whose implicit conversion is better than the corresponding implicit conversion for that argument of F2
. Then the viable function F1
is a better function than the viable function F2
. Hence, a specialization of F1
gets chosen by the overload resolution for the given call.
My questions:
- Have I parsed the whole process correctly?
- Does the compiler need to perform partial ordering at this point? if yes, why?, even though we knowfrom ICS that
F1
is the best viable candidate?
Second Example #2
template <class T> void f(const T&); // F1: reference to const T
template <class T> void f(T*); // F2: pointer to T
f((int*)0);
// matching F1:
// deduction: P = const T&, A = int* --> const T& = int* --> T = int*
// instantiates: void f(int *const&); A = int*, P = int *const&
// S1 conversion: int* --> int* const& (identity conversion)
// matching F2:
// deduction: P = T*, A = int* --> T* = int*; T = int
// instantaies: void f(int*); A = int*, P = int*
// S2 conversion: int* --> int* (identity conversion)
Here neither rule in [over.ics.rank]/3/3.2
is applied; that's both S1
and S2
are identity conversions.
Then the compiler goes to the next step to check the rules defined in [over.match.best.general]/2. Indeed ICSi(F1)
is not a worse conversion sequence than ICSi(F2)
, but the 2.1
bullet is not satisfied because ICSi(F1)
is not a better conversion sequence than ICSi(F2)
. The implicit conversion sequence for the argument of F1
is actually the same (i.e not worse) as that of F2
.
The compiler keeps checking the rules in [over.match.best.general]/2 until it hits bullet 2.5 which says:
- [..]
- (2.5) — F1 and F2 are function template specializations and the
function template for F1 is more specialized than the template for F2
according to the partial ordering rules [..]
I am not going through the whole process of partial ordering, instead, I will summarize things as possible.
Adjustment Function Signature:
void f(T); // Tem1
void f(T*); // Tem2
Transformed Function Signature:
void f(U1); // Tra1
void f(U2*); // Tra2
Matching Tem1
against Tran2
:
void f(T); // Tem1
void f(U2*); // Tra2
// T = U2* - OK: T can be deduced from U2*
Matching Tem2
against Tran1
:
void f(T*); // Tem2
void f(U1); // Tra1
// T* = U1 - error: T cannot be deduced
So template referred by Tra2
is more specialized than the template referred by Tran1
: F2
is more specialized than F1
. Therefore a specialization of F2
will be selected by the overload resolution for the given call.
My questions:
- Have I parsed the whole process correctly?
- What I think (it might be incorrect) is that after template argument deduction, the compiler generates specializations for both overloads to match P/A pairs for the ICS process. Now does the compiler generates a specialization again for the more-specialized template?
Believe me, before posting this question, I searched a lot for a question that covers that whole process. What I need to know, Am I thinking right, and whether all quotes I provided are applied to the examples or not.
Sorry for taking long, and Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论