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)绑定到参数表达式时,隐式转换 sequence是标识转换,除非参数表达式的类型是派生类 参数类型,在这种情况下,隐式转换序列是派生到基础的转换(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) - 如果初始化器是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4)。
(17.2) - 如果目的地类型是参考类型,请参见8.5.3。
8.5.3 [dcl.init.ref] p5
对类型“cv1 T1”的引用由类型为“cv2 T2”的表达式初始化,如下所示:
[...]
(5.2.2.2) - 否则,创建临时类型为“cv1 T1”并从初始化程序复制初始化(8.5) 表达。然后将引用绑定到临时。
[...]
在除最后一个之外的所有情况下(即,从初始化表达式创建和初始化临时), 引用被称为直接绑定到初始化表达式。
问题2 :"直接绑定"包括初始化程序是初始化程序列表的情况?换句话说,我们可以直接使用"绑定"当初始化器是初始化器列表?
注意:"直接绑定"是8.5.3中的定义,由8.5 p17.1引用,"初始化器是一个braced-init-list"是8.5.4中的定义,引自8.5 p17.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],但我可以&#39 ; t看到有关参数的任何单词,这是一个初始化列表。我认为"的定义直接绑定"和#34;论证"与"初始化列表"无关。
当参数是初始化列表并且参数是引用时,您能解释重载解析如何工作吗?
注意:这三个问题相关。当你回答第三个问题时,你将回答第一个和第二个问题。
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
答案 0 :(得分:2)
我们只是有一个缺陷,报告为http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_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&
应该是用户定义的转换,但是当考虑与初始化列表参数隔离的转换时,临时右值将由refefence直接绑定。