Инициализация списка в массиве без временных значений - не работает в GCC

Рассмотрим следующий надуманный пример

struct A {
    A(int) {}
    A(const A&) = delete;
    ~A() {}
};

struct B {
    A a[2] = {{1}, {2}};
};

int main() {
    B b;
}

Он прекрасно компилируется в clang (любая версия), но не в GCC (любая версия, любой стандарт> = С++ 11)

<source>: In constructor 'constexpr B::B()':
<source>:7:8: error: use of deleted function 'A::A(const A&)'
 struct B {
        ^
<source>:3:5: note: declared here
     A(const A&) = delete;
     ^
<source>: In function 'int main()':
<source>:12:7: note: synthesized method 'constexpr B::B()' first required here
     B b;
       ^

LIVE DEMO

Когда деструктор закомментирован, он прекрасно компилируется и в GCC.

Вопрос - кто прав, лязг или GCC и почему?

Первоначально я думал, что GCC не так, но потом я увидел [dcl.init.list]/5, в котором говорится, что создаются временные. Хотя я не уверен, применимо ли это здесь или есть другое правило, которое отменяет это.

Ответы

Ответ 1

Поскольку массив является агрегатом, а агрегатная инициализация сводится к копированию-инициализации агрегатных элементов из элементов списка инициализаторов, вопрос в основном заключается в следующем: выполняет ли копирование-список-инициализацию (элементов массива a[0] и a[1] из {1} и {2}, соответственно) требуется конструктор копирования, но на этот вопрос уже был дан ответ - нет.

Кстати, GCC принимает A a = {1}; то есть у него нет проблем с "прямой" инициализацией копирования списка, но он не обрабатывает это правильно, когда члены агрегатов инициализируются.

Ответ 2

Это, среди миллионов других причин, является причиной того, что так много людей оставляют этот отвратительный язык позади и переходят к гораздо лучшим вещам.