Bri*_*ian 5 c++ overload-resolution
考虑以下代码:
#include <cstdio>
struct S {
S(int) {}
};
void f(const S&) { std::puts("const S&"); }
void f(S&&) { std::puts("S&&"); }
int main() {
f(42);
}
Run Code Online (Sandbox Code Playgroud)
很明显,GCC 和 Clang 都同意应该调用重载S&&,但我对标准的解读是,实际上没有规则要求这种情况!
当然,您会说调用f必须初始化一个临时S对象,并且重载解析更喜欢将右值引用绑定到右值而不是绑定左值引用。然而,这就是标准在 [over.ics.rank]/(3.2) 中实际所说的内容:
标准转换序列
S1是比标准转换序列更好的转换序列,S2如果...
S1和S2是引用绑定 (11.6.3),两者都不引用未使用ref-qualifier声明的非静态成员函数的隐式对象参数,并且S1将右值引用绑定到右值并S2绑定左值引用...
因此,有关左值和右值引用绑定的决胜局仅适用于标准转换序列。但是需要用户定义的f转换序列才能调用给定int参数的任一重载。用户自定义转换序列的排序规则为(3.3),
如果用户定义的转换序列
U1包含相同的用户定义的转换函数或构造函数,或者它们在聚合初始化中初始化相同的类,并且在这两种情况下,第二个标准转换序列是,则用户定义的转换序列是U2比另一个用户定义的转换序列更好的转换序列U1优于 的第二个标准转换序列U2。
显然,两个转换序列(toconst S&和S&&)都调用相同的构造函数,因此如果第二个标准转换优于第一个标准转换,则第二个转换序列可能优于第一个。然而,[over.ics.ref]/2 说:
当引用类型的参数没有直接绑定到参数表达式时,转换序列就是根据 16.3.3.1 将参数表达式转换为引用类型所需的序列。从概念上讲,此转换序列对应于使用参数表达式复制初始化引用类型的临时值。顶级简历资格中的任何差异都包含在初始化中,并且不构成转换。
根据我的阅读, to 的隐式转换序列int与toconst S&的用户定义转换序列相同,这只是一个用户定义的转换,第二个标准转换是恒等转换;同样, to的隐式转换序列与to的用户定义转换序列相同,后者也是单个用户定义的转换,其中第二个标准转换是恒等转换。intconst SintS&&intS
因此,第二个重载的“明显”选择没有文本基础……或者我是否缺少一个?
| 归档时间: |
|
| 查看次数: |
94 次 |
| 最近记录: |