C++ 当需要用户定义的转换时,左值和右值引用参数之间的重载解析
考虑以下代码:C++ 当需要用户定义的转换时,左值和右值引用参数之间的重载解析,c++,overload-resolution,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); } #包括 结构{ S(int){} }; void f(常数S&){std::put(“常数S&”)} void f(S&&
#include <cstdio>
struct S {
S(int) {}
};
void f(const S&) { std::puts("const S&"); }
void f(S&&) { std::puts("S&&"); }
int main() {
f(42);
}
#包括
结构{
S(int){}
};
void f(常数S&){std::put(“常数S&”)}
void f(S&&{std::put(“S&&”)}
int main(){
f(42);
}
显然,应该调用S&&
重载,但我对标准的理解是,实际上没有规则要求这种情况
当然,您会说对f
的调用必须初始化一个临时S
对象,重载解析更倾向于将右值引用绑定到右值,而不是绑定左值引用。然而,这是标准在[over.ics.rank]/(3.2)中实际说明的:
标准转换顺序S1
比标准转换顺序S2
更好
和S1
是引用绑定(11.6.3),都不引用未声明ref限定符的非静态成员函数的隐式对象参数,并且S2
将右值引用绑定到右值,而S1
绑定左值引用S2
int
参数,则需要用户定义的转换序列来调用f
的重载。对用户定义的转换序列进行排序的规则为(3.3)
如果用户定义的转换序列U1
包含相同的用户定义转换函数或构造函数,或者在聚合初始化中初始化相同的类,并且在任何一种情况下都是U1
优于U2
的第二个标准转换序列
显然,两个转换序列(toconst S&
和S&&
)调用同一个构造函数,因此如果第二个标准转换优于第一个,则第二个可能优于第一个。但是,[over.ics.ref]/2说:
当引用类型的参数未直接绑定到参数表达式时,根据16.3.3.1,转换序列是将参数表达式转换为引用类型所需的序列。从概念上讲,此转换序列对应于使用参数表达式初始化引用类型的临时副本。顶级简历资格的任何差异均包含在初始化中,不构成转换
根据我的阅读,int
到const S&
的隐式转换序列与int
到const S
的用户定义转换序列相同,这只是一个用户定义的转换,第二个标准转换是身份转换;类似地,int
到S&
的隐式转换序列与int
到S
的用户定义转换序列相同,这也是单个用户定义转换,第二个标准转换是身份转换
因此,第二个重载的“明显”选择没有文本基础。。。还是有一个我错过了?Hm。。。绑定到
常量&
不需要额外的限定转换吗?(如果你有一个常量&&
重载,也一样。)我不认为这个限定是“顶级的”。@KerrekSB段落说:“转换序列是将参数表达式转换为引用类型所需的序列”。因此,无论将int
转换为const S
(此处,cv限定为顶级)需要什么用户定义的转换序列,都需要完全相同的用户定义转换序列(具有相同的重载解析含义)来将int
转换为const S&
,因此不需要,没有额外的资格转换。