直接列表初始化编译成功,但是正常的直接初始化失败,为什么?

Direct list initialization compiles successfully, but normal direct initialization fails, why?

例如,代码如下:

struct A { A(int); };
struct B { B(A);   };

int main()
{
    B b{{0}}; // OK
    B c({0}); // error
}

错误信息是:

f.cc: In function 'int main()':
f.cc:7:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
  B c({0}); // error

         ^
f.cc:7:9: note: candidates are:
f.cc:2:12: note: B::B(A)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(const B&)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(B&&)

截至最新的官方标准C++14,您的第一次初始化没有歧义。 [over.match.list]:

由于不存在初始化列表构造函数,我们输入 "second phase"。现在考虑 [over.best.ics]/4:

我们的元素是{0}。因此这不允许复制构造函数的(用户定义的)转换{0} -> A。显然,如果我们不在 [over.match.list] 的第二阶段,这不适用,因此对于 B c({0}) 的示例,c 和两个构造函数都不会发生列表初始化被考虑。


CWG 问题 1467

第一次初始化目前与第二次初始化一样不明确。编译器还没有实现 CWG #1467 - 它的决议删除了上面引用的要点 (4.5)。
请参阅 #2076,它选择还原更改:

The resolution of issue 1467 made some plausible constructs ill-formed. For example,

struct A { A(int); };
struct B { B(A); };
B b{{0}};

This is now ambiguous, because the text disallowing user-defined conversions for B's copy and move constructors was removed from 13.3.3.1 [over.best.ics] paragraph 4.

"The text" 是前面提到的要点。理查德史密斯提出以下措辞:

For non-class types, we allow initialization from a single-item list to perform a copy only if the element within the list is not itself a list (13.3.3.1.5 [over.ics.list] bullet 9.1). The analogous rule for this case would be to add back the bullet in 13.3.3.1 [over.best.ics] paragraph 4, but only in the case where the initializer is itself an initializer list:

        the second phase of 13.3.1.7 [over.match.list] when the initializer list has exactly one         element that is itself an initializer list, where the target is the first parameter of a constructor
        of class X, and the conversion is to X or reference to (possibly cv-qualified) X,

因为初始化器 {0} 本身就是一个初始化器列表,所以该要点将使您的第一个初始化再次合式。