Инициализация значения С++ 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]:

Функция предоставляется пользователю, если она объявлена ​​пользователем и не явно по умолчанию или удалено в его первом объявлении.