Начиная с последнего официального стандарта, C ++ 14, ваша первая инициализация не является двусмысленной. [over.match.list]:
Поскольку не существует конструкторов-списков инициализаторов, мы вводим «вторую фазу». А теперь рассмотрим [over.best.ics] / 4:
Наш элемент {0}
. Следовательно, это запрещает (определяемое пользователем) преобразование {0}
-> A
для конструктора копирования. Ясно, что это не применяется, если мы не находимся во второй фазе [over.match.list], поэтому для вашего примера с B c({0})
не выполняется инициализация списка для c
и оба конструктора рассматриваются.
Первая инициализация в настоящее время столь же неоднозначна, как и вторая. Компиляторы просто еще не реализовали CWG # 1467 - его разрешение удалено из пункта пули (4.5), приведенное выше. См. # 2076 , в котором предлагается вернуться к изменению:
Разрешение issue 1467 сделало некоторые правдоподобные конструкции плохо сформированными. Например,
struct A { A(int); }; struct B { B(A); }; B b{{0}};
Это теперь неоднозначно, потому что текст, запрещающий определенные пользователем преобразования для конструкторов копирования и перемещения
blockquote>B
, был удален из пункта 13.3.3.1 [over.best.ics] 4.«Текст» - это упомянутая выше маркерная точка. Ричард Смит предлагает следующую формулировку:
Для типов, отличных от класса, мы разрешаем инициализацию из списка отдельных элементов для выполнения копии только в том случае, если элемент внутри списка сам по себе не является списком (13.3 .3.1.5 [over.ics.list] bullet 9.1). Аналогичным правилом для этого случая было бы добавить обратно маркер в пункт 13.3.3.1 [over.best.ics], но только в том случае, когда инициализатор сам является списком инициализаторов:
& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; вторая фаза 13.3.1.7 [over.match.list], когда список инициализаторов имеет ровно один & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; ; элемент, который сам является списком инициализаторов, где целью является первый параметр конструктора & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp ;, и преобразование равно
blockquote>X
ссылка на (возможно, cv-qualified)X
,Поскольку инициализатор
{0}
сам является списком инициализаторов, эта точка маркера сделает вашу первую инициализацию хорошо сформированной.