Инициализация значения C++14 с удаленным конструктором

У меня есть недоразумение:

Давайте отметим конструктор по умолчанию для структуры A как удаленный:

struct A
{
  A() = delete;
};

Следующая инструкция правильно сформирована и что это за эффект?:

A a{};

Из инициализации значения cppreference:

1) Если T является типом класса без конструктора по умолчанию или с предоставленным пользователем конструктором по умолчанию или с удаленным конструктором по умолчанию, объект инициализируется по умолчанию.

но тогда эффект инициализации по умолчанию:

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

Или это совокупная инициализация? Спасибо!

2 ответа

Решение

Ваш 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):

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

Это хорошо сформировано. A является агрегатом1, и, согласно проекту N3936, пустой список инициализатора, используемый при инициализации прямого списка агрегата, приводит к инициализации агрегата:

Из п. 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

....

- конец примера]

....

Соответствующие изменения между C++11 и C++1y - это изменение приоритета инициализации агрегата по сравнению со значением для случая агрегатов:

C++11 ведет с

Инициализация списка объекта или ссылки типа T определяется следующим образом:

- Если список инициализаторов не имеет элементов и T является типом класса с конструктором по умолчанию, объект инициализируется значением.

- В противном случае, если T является агрегатом, выполняется агрегатная инициализация (8.5.1)....

сопровождаемый примером выше.

C++1y отдает приоритет агрегатной инициализации:

Инициализация списка объекта или ссылки типа T определяется следующим образом:

- Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).

....

- В противном случае, если список инициализаторов не имеет элементов и T является типом класса с конструктором по умолчанию, объект инициализируется значением.


1 Почему A совокупность?

Это совокупность как в C++11, так и в C++ 14.

C++1y:

8.5.1 Агрегаты [dcl.init.aggr]

Агрегат - это массив или класс (раздел 9) без предоставленных пользователем конструкторов (12.1), без закрытых или защищенных нестатических элементов данных (пункт 11), без базовых классов (пункт 10) и без виртуальных функций (10.3).

Единственная часть, которая не очевидна - это то, предоставлен конструктор по умолчанию или нет. Это не:

В § 8.4.2 [dcl.fct.def.default]:

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

Другие вопросы по тегам