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


Разрешено ли это в стандарте:

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

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

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

1 31

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: инициализаторы членов и агрегаты , который имеет следующий абстрактный вид:

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

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

Агрегаты не могут иметь определяемые пользователем конструкторы и инициализаторы членов, по существу, являются своего рода определяемыми пользователем конструктор (элемент) (см. Также дефект ядра 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

Смотрите, как это работает [63]}жить .