Ответ 1
const S s3;
Подпадает под действие [dcl.init]/12:
Если для объекта не задан инициализатор, объект инициализируется по умолчанию.
Таким образом, согласно вашей цитате, должен присутствовать предоставленный пользователем конструктор по умолчанию. Добавляя один так,
struct S {
int a = 1;
constexpr S(){}
};
тогда делает компиляцию объявления.
[..] особенно, когда тип не является совокупностью.
S
- это совокупность в вашем случае, и причина, по которой const S s{}
действительна. Агрегатная инициализация применяется для const S s{}
, и все отлично.
Если S
не является совокупностью,
Список-инициализация объекта или ссылки типа T определяется как следующим образом:
- Если
T
является агрегатом, выполняется агрегатная инициализация (8.5.1).- В противном случае, если в списке инициализаторов нет элементов, а
T
- это тип класса со стандартным конструктором, объект инициализируется значением.
Теперь рассмотрим определение инициализации значения:
Для инициализации объекта с типом
T
означает:
- если
T
является (возможно, cv-qualit) тип класса (раздел 9), либо без дефолта конструктор (12.1) или конструктор по умолчанию, который предоставляется или удаляется пользователем, тогда объект инициализируется по умолчанию;- , если
T
является (возможно, cv-qualit) без пользовательского или удаленного значения по умолчанию конструктор, тогда объект инициализируется нулем, а семантические ограничения для инициализации по умолчанию проверяются, и еслиT
имеет нетривиальный конструктор по умолчанию, объект инициализируется по умолчанию;
Значение по умолчанию ctor действительно нетривиально, так как элемент имеет инициализатор ([class.ctor]/4.9), но это не имеет значения, поскольку ограничения проверяются в любом случае. Следовательно, инициализация по умолчанию - это, а строка
const S s{};
Точно так же (или недействительно!) как
const S t;
Итак, почему gcc разрешает это
Ну:
-
Говоря о существующих стандартах, GCC не соответствует требованиям; См. Выше.
-
Существует активная проблема CWG, # 253, созданная пятнадцать лет назад, которая охватывает аналогичный сценарий. В заключительной записке об этом из собрания 2011 года говорится:
Если неявный конструктор по умолчанию инициализирует все подобъекты, не требуется инициализатор.
Это относится к неявному конструктору по умолчанию для
S
, и это сделает все ваши строки действительными. -
Разработчики GCC (например, здесь) подразумевали, что, поскольку комитет в основном согласился с этой резолюцией, текущее поведение GCC возможен и не должен корректироваться. Поэтому можно утверждать, что GCC прав, и стандарт нарушен.