Инициализация значения С++ 14 с удаленным конструктором
У меня есть недоразумение:
Отметьте по умолчанию конструктор структуры A как удаленный:
struct A
{
A() = delete;
};
Следующая инструкция хорошо сформирована и какой эффект?
A a{};
От инициализация значения cppreference:
1) Если T - тип класса без конструктора по умолчанию или с предоставленный пользователем конструктор по умолчанию или с удаленным значением по умолчанию конструктор, объект инициализируется по умолчанию.
но тогда эффект инициализации по умолчанию:
Если T является типом класса, конструктор по умолчанию вызывается для обеспечения начальное значение для нового объекта.
Или это сводная инициализация?
Спасибо!
Ответы
Ответ 1
Ваш struct A
:
- тип класса, который имеет:
- нет конструкторов, предоставляемых пользователем 1,
- нет частных или защищенных нестатических членов данных,
- нет базовых классов,
- нет виртуальных функций-членов.
Поэтому он квалифицируется как совокупный тип в соответствии с определением, изложенным в § 8.5.1/1.
Затем выполняется приоритет инициализации агрегата по инициализации значения. В стандарте говорится, что агрегатная инициализация имеет приоритет перед инициализацией стоимости (проект N3936, § 8.5.4/3, стр. 201) (выделено мной)
Список-инициализация объекта или ссылки типа T определяется следующим образом:
- Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).
- В противном случае, если в списке инициализаторов нет элементов, а T - тип класса с конструктором по умолчанию, объект инициализируется значением.
- [... больше правил...]
(1) Как указано в комментариях о том, почему удаленный конструктор не учитывается как определяемый пользователем, вот что говорит стандарт (проект N3936, § 8.4.2/5, стр. 198):
Функция предоставляется пользователем, если она объявлена пользователем и явно не дефолтна или не удалена в ее первом объявлении.
Ответ 2
Он хорошо сформирован. A
представляет собой совокупность 1 и, согласно проекту N3936, пустой список инициализаторов, используемый в прямом -list инициализация совокупного результата в совокупной инициализации:
От § 8.5.4/3 List-initialization [dcl.init.list]:
Список-инициализация объекта или ссылки типа T определяется следующим образом:
- Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).
[Пример:
struct S2 { int m1; double m2, m3; };
....
S2 s23{}; // OK: default to 0,0,0
....
- конец примера]
....
Соответствующие изменения между С++ 11 и С++ 1y - это изменение в приоритете инициализации агрегата и значения для случая агрегатов:
С++ 11 ведет с
Список-инициализация объекта или ссылки типа T определяется как следует:
- Если в списке инициализаторов нет элементов, а T - класс type с конструктором по умолчанию, объект инициализируется значением.
- В противном случае, если T является агрегатом, выполняется агрегатная инициализация (8.5.1)....
а затем пример выше.
С++ 1y дает приоритет агрегатной инициализации:
Список-инициализация объекта или ссылки типа T определяется следующим образом:
- Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).
....
- В противном случае, если в списке инициализаторов нет элементов, а T - тип класса с конструктором по умолчанию, объект инициализируется значением.
1 Почему A
агрегат?
Это совокупность как в С++ 11, так и в С++ 14.
С++ 1y:
8.5.1 Агрегаты [dcl.init.aggr]
Агрегат - это массив или класс (раздел 9) без конструкторов, предоставляемых пользователем (12.1), без частных или защищенных нестатических элементов данных (раздел 11), без базовых классов (раздел 10) и без виртуальных функции (10.3).
Единственная часть, которая не очевидна, заключается в том, предоставлен ли по умолчанию конструктор для пользователя или нет. Это не:
В § 8.4.2 [dcl.fct.def.default]:
Функция предоставляется пользователю, если она объявлена пользователем и не явно по умолчанию или удалено в его первом объявлении.