Следующий пример инициализации std::array <char, N>
член в конструкторе, использующий строковый литерал, не компилируется в GCC 4.8, но компилируется с использованием Clang 3.4.
#include <iostream>
#include <array>
struct A {
std::array<char, 4> x;
A(std::array<char, 4> arr) : x(arr) {}
};int main() {
// works with Clang 3.4, error in GCC 4.8.
// It should be the equivalent of "A a ({'b','u','g','\0'});"A a ({"bug"});
for (std::size_t i = 0; i < a.x.size(); ++i)
std::cout << a.x[i] << '\n';
return 0;
}
На первый взгляд это похоже на ошибку GCC. Я чувствую, что это должно скомпилироваться, так как мы можем инициализировать std::array<char, N>
непосредственно со строковым литералом. Например:
std::array<char, 4> test = {"bug"}; //works
Мне было бы интересно посмотреть, что стандарт говорит об этом.
Да, ваш код действителен; это ошибка в gcc.
Вот более простая программа, которая демонстрирует ошибку (я заменил std::array<char, 4>
с S
и избавился от A
, как мы можем продемонстрировать ошибку только при возврате функции (это упрощает анализ, так как нам не нужно беспокоиться о перегрузке конструктора):
struct S { char c[4]; };
S f() { return {"xxx"}; }
Здесь у нас есть целевой объект типа S
то есть копия инициализируется (8.5p15) из приготовился-INIT-лист {"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.
Других решений пока нет …