c – 当参数是初始化列表且参数是引用时的重载决策

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 When an argument is an initializer list (8.5.4), it is not an expression and special rules apply for converting
it to a parameter type.

8 Otherwise, if the parameter is a reference, see 13.3.3.1.4.

13.3.3.1.4 [over.ics.ref] p1和p2

1 When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversion
sequence is the identity conversion, unless the argument expression has a type that is a derived class of the
parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion (13.3.3.1). [ Example… ]

If the parameter binds directly to the result of applying a conversion function to the
argument expression, the implicit conversion sequence is a user-defined conversion sequence (13.3.3.1.2),
with the second standard conversion sequence either an identity conversion or, if the conversion function
returns an entity of a type that is a derived class of the parameter type, a derived-to-base Conversion.

2 When a parameter of reference type is not bound directly to an argument expression, the conversion sequence
is the one required to convert the argument expression to the underlying type of the reference according
to 13.3.3.1. Conceptually, this conversion sequence corresponds to copy-initializing a temporary of the
underlying type with the argument expression. Any difference in top-level cv-qualification is subsumed by
the initialization itself and does not constitute a conversion.

问题1:“参数表达式”是否包含“初始化列表”?见上面的13.3.3.1.5 [over.ics.list] p1粗体短语和

1.3.2 [defns.argument]

argument

<function call expression> expression in the comma-separated list bounded by the parentheses (5.2.2)

8.5 [dcl.init] p17

17 The semantics of initializers are as follows. The destination type is the type of the object or reference being
initialized and the source type is the type of the initializer expression. If the initializer is not a single (possibly
parenthesized) expression, the source type is not defined.

(17.1) — If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).

(17.2) — If the destination type is a reference type, see 8.5.3.

8.5.3 [dcl.init.ref] p5

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

[…]

(5.2.2.2) — Otherwise, a temporary of type “cv1 T1” is created and copy-initialized (8.5) from the initializer
expression. The reference is then bound to the temporary.

[…]

  
  在除了最后一个之外的所有情况下(即,从初始化表达式创建和初始化临时),
  据说引用直接绑定到初始化表达式.

问题2:“直接绑定”是否包括初始化程序是初始化程序列表的情况?换句话说,当初始化器是初始化器列表时,我们可以使用“直接绑定”吗?

注:“直接绑定”是8.5.3中的定义,由8.5 p17.1引用,“initializer是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],但我看不到任何单词关于作为初始化列表的参数.我认为“直接绑定”和“参数”的定义与“初始化列表”无关.

你可以解释当参数是初始化列表并且参数是引用时,重载解析如何工作?

注意:这三个问题是相关的.当你回答第三个问题时,你将回答第一个和第二个问题.

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

最佳答案 我们只是有一个缺陷,报告为
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&应该是用户定义的转换,但在考虑与初始化列表参数隔离的转换时,临时rvalue将由refefence直接绑定.

点赞