C++11 агрегатная инициализация для классов с нестатическими инициализаторами членов

Это разрешено в стандарте:

struct A
{
  int a = 3;
  int b = 3;
};

A a{0,1}; // ???

Этот класс все еще агрегирован?clang принимает этот код, но gcc не делает.

1 ответ

Решение

В C++11 наличие инициализаторов членов класса делает структуру / класс не агрегатной - однако это изменилось в C++14. Это то, что мне показалось удивительным, когда я впервые столкнулся с этим, обоснование этого ограничения заключается в том, что инициализаторы в классе очень похожи на определяемый пользователем конструктор, но контраргумент состоит в том, что никто не ожидает, что добавление инициализаторов в классе должно сделать их класс / структура не агрегатные, я уверен, что нет.

Из проекта стандартного раздела C++11 8.5.1 Агрегаты (выделение мое вперед):

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

и в C++14 этот же абзац гласит:

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

Это изменение описано в N3605: Инициализаторы элементов и агрегаты, которые имеют следующее резюме:

Бьярн Страуструп и Ричард Смит подняли вопрос о том, что инициализация агрегатов и инициализаторы членов не работают вместе. В этой статье предлагается решить эту проблему, приняв предложенную Смитом формулировку, которая снимает ограничение, согласно которому агрегаты не могут иметь инициализаторы элементов.

Этот комментарий в основном подводит итог нежеланию позволить им быть совокупностями:

Агрегаты не могут иметь пользовательских конструкторов, а инициализаторы-члены по сути являются своего рода пользовательским конструктором (элементом) (см. Также Core Defect 886). Я не против этого расширения, но оно также влияет на то, какова наша модель агрегатов. После принятия этого расширения я хотел бы узнать, как преподавать, что такое агрегат.

Пересмотренная версия N3653 была принята в мае 2013 года.

Обновить

emsr указывает, что G++ 5.0 теперь поддерживает агрегаты C++14 с нестатическими инициализаторами элементов данных, использующими либо std=c++1y или же -std=c++14:

struct A { int i, j = i; };
A a = { 42 }; // a.j is also 42

Вижу это работает вживую.

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