Ваша проблема связана с агрегатной инициализацией: struct X
является агрегатом, а struct Y
— нет. Вот стандартная цитата об агрегатах (8.5.1):
Агрегат представляет собой массив или класс (раздел 9) без конструкторов, предоставляемых пользователем (12.1), без инициализаторов с фигурными скобками или равными для нестатических элементов данных (9.2), без закрытых или защищенных нестатических элементов данных ( Раздел 11), без базовых классов (Статья 10) и без виртуальных функций (10.3).
Это предложение указывает, что если class
имеет базовый класс, то это не агрегат. Здесь struct Y
имеет struct X
в качестве базового класса и, следовательно, не может быть агрегатным типом.
Что касается вашей конкретной проблемы, возьмите следующий пункт из стандарта:
Когда агрегат инициализируется списком инициализаторов, как указано в 8.5.4, элементы списка инициализаторов берутся в качестве инициализаторов для членов агрегата в порядке возрастания индекса или членов. Каждый элемент инициализируется копированием из соответствующего предложения инициализатора. Если предложение-инициализатор является выражением, и для преобразования выражения требуется сужающее преобразование (8.5.4), программа имеет неправильный формат.
Когда вы делаете X x = {0}
, агрегатная инициализация используется для инициализации a
до 0
. Однако когда вы делаете Y y = {0}
, поскольку struct Y
не является агрегатным типом, компилятор будет искать подходящий конструктор. Поскольку ни один из неявно сгенерированных конструкторов (по умолчанию, копирование и перемещение) не может ничего сделать с одним целым числом, компилятор отвергает ваш код.
Что касается этого поиска конструкторов, сообщения об ошибках от clang++ немного более явно указывают на то, что на самом деле пытается сделать компилятор (онлайн-пример):
Y Y = {0};
^ ~~~
main.cpp:5:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Y &' for 1st argument
struct Y : public X {};
^
main.cpp:5:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Y &&' for 1st argument
struct Y : public X {};
^
main.cpp:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
Обратите внимание, что есть предложение расширить инициализацию агрегатов для поддержки ваш вариант использования, и он перешел в C++17. Если я правильно прочитал, это делает ваш пример действительным с ожидаемой семантикой. Итак... вам нужно только дождаться компилятора, совместимого с С++ 17.
person
Morwenn
schedule
07.06.2013