struct A { A(int);};
struct B { explicit B(A); B(const B&);};
B b({0}); 我问了一个问题,Overload resolution gets different result between gcc and clang和@Johannes Schaub - litb解释了现行的规则。但是,对于13.3.3.1.4引用绑定,我仍然有一些疑问。
N4527 13.3.3.1.5 over.ics.list p1和p8
1当参数是初始化程序列表(8.5.4)时,不是表达式,并且应用特殊规则将其转换为参数类型。 8否则,如果参数是引用,请参见13.3.3.1.4。
13.3.3.1.4 over.ics.ref p1和p2
1当引用类型的参数直接将 (8.5.3)绑定到参数表达式时,隐式转换序列就是身份转换,除非参数表达式的类型是参数类型的派生类,在这种情况下,隐式转换序列是派生到基的转换(13.3.3.1)。例如..。 如果参数直接绑定到将转换函数应用于参数表达式的结果,则隐式转换序列是用户定义的转换序列(13.3.3.1.2),第二个标准转换序列要么是身份转换,要么是如果转换函数返回作为参数类型派生类的类型的实体,则是派生到基的转换。 2当引用类型的参数不直接将绑定到参数表达式时,转换序列是根据13.3.3.1将参数表达式转换为引用的底层类型所必需的序列。从概念上讲,此转换序列对应于使用参数表达式对基础类型的临时进行复制初始化。顶级cv限定中的任何差异都包含在初始化本身中,并不构成转换。
问题1:“参数表达式”是否包括“初始化程序列表”?见13.3.3.1.5 over.ics.list p1粗体短语和
1.3.2 defns.argument
论据 以括号为界的逗号分隔列表中的表达式(5.2.2)
8.5 dcl.init p17
17初始化器的语义如下。目标类型是正在初始化的对象或引用的类型,源类型是初始化器表达式的类型。如果初始化器不是单个(可能是括号大小)表达式,则不定义源类型。 (17.1) -如果初始化器是(非括号大小的)大括号内列表,则对象或引用是列表初始化(8.5.4)。 (17.2) -如果目标类型是引用类型,请参见8.5.3。
8.5.3 dcl.init.ref p5
类型“cv1 T1”的引用由“cv2 T2”类型的表达式初始化,如下所示: ... -否则,将创建一个类型为“cv1 T1”的临时类型,并从初始化器表达式复制初始化(8.5)。然后,引用被绑定到临时的。 ..。在所有情况下,除了最后一种情况(即从初始化器表达式创建和初始化临时表达式),引用被称为直接将绑定到初始化器表达式。
问题2:“绑定”是否包括初始化程序列表的情况?换句话说,当初始化程序是初始化程序列表时,我们可以直接使用“绑定”吗?
注:"bind直接“是8.5.3中的定义,由8.5页17.1引用;”初始化器是括号-init-list“是8.5.4中的定义,由8.5页17.2引用。
//case 5.2.1.2
struct X{};
struct Y{Y(X);};
const Y& y1 = X(); // bind directly
const Y& y2 = {X()}; // bind directly or not?
struct Z{operator X();};
const X& x1 = Z(); // bind directly
const X& x2 = {Z()}; // bind directly or not?
//case 5.2.2.1
struct A{operator int();};
const int& a1 = A(); // bind directly
const int& a2 = {A()}; // bind directly or not?
struct B{B(int);};
const B& b1 = 1; // bind directly
const B& b2 = {1}; // bind directly or not?
//csse 5.2.2.2
int i3 = 2;
double&& rrd3 = i3; // not bind directly
struct A { A(int);};
struct B { explicit B(A); B(const B&);};
B b({0}); // when overload resolution choose B(const B&) as a candidate,
// {0} -> constB& bind directly or not? 问题3(主要问题):
当一个参数是一个初始化程序列表并且参数是一个引用时,13.3.3.1.5 over.ics.list p8引用13.3.3.1.4 over.ics.ref,但是我看不到任何关于参数的单词,它是一个初始化程序列表。我认为“直接绑定”和“参数”的定义与“初始化程序列表”无关。
当参数是初始化程序列表而参数是引用时,您能解释重载解析是如何工作的吗?
注意:这三个问题是与相关的。当你回答第三个问题时,你会回答第一个和第二个问题。
struct A { A(int);};
struct B { explicit B(A); B(const B&);};
B b1(0); //when overload resolution choose B(const B&) as a candidate,
//0 -> const B& binds directly
//13.3.3.1.4 [over.ics.ref] p1 "If the parameter binds directly..."
A a;
B b2(a) //when overload resolution choose B(const B&) as a candidate,
//a -> const B& binds directly
//13.3.3.1.4 [over.ics.ref] p1 "If the parameter binds directly..."
B b3({0})//when overload resolution choose B(const B&) as a candidate,
//{0} -> const B& binds directly or not?
//if it is not bound directly, 13.3.3.1.4 [over.ics.ref] p2
B b3({a})//when overload resolution choose B(const B&) as a candidate,
//{a} -> const B& binds directly or not?
//if it is not bound directly, 13.3.3.1.4 [over.ics.ref] p2发布于 2015-10-13 12:16:35
我们只是有一个缺陷,被报告为active.html#1536 (我刚刚发现,在编写另一个答案时不知道这个报告)。
over.ics.ref完全与初始化程序列表无关,并且正在讨论创建的临时程序(由decl.init.list创建)绑定到引用,这一解释对我来说似乎是个问题。特别是,over.ics.list说over.ics.ref将委托over.ics.list初始化临时,这表明在创建临时之前over.ics.ref已经处于活动状态(在decl.init.list中也有没有创建临时的情况)。另外,{ }到ClassType&应该是用户定义的转换,但是在考虑从初始化程序列表参数分离出来的转换时,临时rvalue将直接由refefence绑定。
https://stackoverflow.com/questions/33074102
复制相似问题