Ответ 1
b
- совокупность. Когда вы инициализируете его с помощью списка инициализаторов, элементы в списке инициализируют первые n членов агрегата, где n - количество элементов в списке. Остальные элементы агрегата инициализируются списком-списком.
Таким образом, в вашем примере c
будет инициализироваться с помощью списка копий, но это плохо сформировано, если выбранный конструктор explicit
, следовательно, ошибка.
Соответствующие стандартные котировки
Когда агрегат инициализируется списком инициализаторов, как указано в [dcl.init.list], элементы списка инициализаторов берутся как инициализаторы для элементов агрегата. Явно инициализированные элементы совокупности определяются следующим образом:
...
- Если список инициализаторов является списком инициализаторов, явно инициализированные элементы агрегата являются первыми n элементами агрегата, где n - количество элементов в списке инициализаторов.
- В противном случае список инициализаторов должен быть{}
, и нет явно инициализированных элементов.
Для неединичной совокупности каждый элемент, который не является явно инициализированным элементом, инициализируется следующим образом:
...
- В противном случае, если элемент не является ссылкой, элемент инициализируется копией из пустого списка инициализаторов ([dcl.init.list]).
Эффект инициализации копирования c
из пустого списка инициализаторов описан в
Инициализация списка объекта или ссылки типа
T
определяется следующим образом:
...
- В противном случае, если в списке инициализаторов нет элементов, аT
- тип класса с конструктором по умолчанию, объект инициализируется значением.
Для инициализации объекта типа
T
означает:
...
- еслиT
- тип класса (возможно, cv-qualit) без конструктора по умолчанию ([class.ctor]) или конструктора по умолчанию, который предоставляется или удаляется пользователем, тогда объект инициализируется по умолчанию;
По умолчанию инициализировать объект типа
T
:
- Если T является классом класса (возможно, cv-qualit), рассматриваются конструкторы. Соответствующие конструкторы перечисляются ([over.match.ctor]), а лучший для инициализатора() выбирается посредством разрешения перегрузки. Выбранный таким образом конструктор вызывается с пустым списком аргументов для инициализации объекта.
... Для инициализации копии, функции-кандидаты являются всеми конструкторами преобразования этого класса.
Конструктор, объявленный без
explicit
спецификатора функции, указывает преобразование из типов его параметров (если есть) в тип своего класса. Такой конструктор называется конструктором преобразования.
В приведенном выше примере a
не имеет преобразовывающих конструкторов, поэтому разрешение перегрузки выходит из строя. Пример (ненормативный) в [class.conv.ctor]/2 даже содержит очень похожий случай
struct Z { explicit Z(); explicit Z(int); explicit Z(int, int); }; Z c = {}; // error: copy-list-initialization
Вы можете избежать ошибки, предоставив инициализатор элемента по умолчанию для c
struct b
{
a c{}; // direct-list-initialization, explicit ctor is OK
};