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

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

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

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

int main() {
    B b;
}

Он отлично компилируется в clang (любая версия), но не в GCC (любая версия, любой стандарт> =C ++ 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

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

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

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

1 Ответ

3 голосов
/ 29 апреля 2019

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

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

...