参数是初始化列表且参数是引用

时间:2015-10-12 05:52:45

标签: c++ c++11 language-lawyer overload-resolution list-initialization

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

1 个答案:

答案 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直接绑定。