Ответ 1
Да, ваш код действителен; это ошибка в gcc.
Вот более простая программа, демонстрирующая ошибку (я заменил std::array<char, 4>
на S
и избавился от A
, так как мы можем продемонстрировать ошибку только в возврате функции (это упрощает анализ, поскольку мы не нужно беспокоиться о перегрузке конструктора):
struct S { char c[4]; };
S f() { return {"xxx"}; }
Здесь у нас есть целевой объект типа S
, который инициализируется с копией (8.5p15) из списка с привязкой к элементарной строке {"xxx"}
, поэтому объект инициализируется списком (8.5p17b1). S
является агрегатом (8.5.1p1), поэтому выполняется агрегатная инициализация (8.5.4p3b1). В агрегатной инициализации член c
инициализируется копированием из соответствующего предложения-инициализатора "xxx"
(8.5.1p2). Вернемся к 8.5p17 с целевым объектом типа char[4]
и инициализируем строковый литерал "xxx"
, поэтому 8.5p17b3 относится к 8.5.2, а элементы массива char
инициализируются последовательными символами строки (8.5.2p1).
Обратите внимание, что gcc отлично работает с инициализацией копирования S s = {"xxx"};
при разбиении на различные формы копирования и прямой инициализации; передача аргументов (включая конструкторам), возврат функции и инициализация базы и элемента:
struct S { char c[4]; };
S f() { return {"xxx"}; }
void g(S) { g({"xxx"}); }
auto p = new S({"xxx"});
struct T { S s; T(): s({"xxx"}) {} };
struct U: S { U(): S({"xxx"}) {} };
S s({"xxx"});
Последнее особенно интересно, поскольку это указывает на то, что это может быть связано с ошибка 43453.