Initializing std::array<char,x> member in constructor using string literal. GCC bug?

c++, c++11, compiler-bug, gcc, stdarray

Solution

Yes, your code is valid; this is a bug in gcc.

Here's a simpler program that demonstrates the bug (I've replaced `std::array<char, 4>` with `S` and got rid of `A`, as we can demonstrate the bug just in function return (this makes the analysis simpler, as we don't have to worry about constructor overloading):

struct S { char c[4]; };
S f() { return {"xxx"}; }

Here we have a destination object of type `S` that is copy-initialized (8.5p15) from the braced-init-list `{"xxx"}`, so the object is list-initialized (8.5p17b1). `S` is an aggregate (8.5.1p1) so aggregate initialization is performed (8.5.4p3b1). In aggregate initialization, the member `c` is copy-initialized from the corresponding initializer-clause `"xxx"` (8.5.1p2). We now return to 8.5p17 with destination object of type `char[4]` and initializer the string literal `"xxx"`, so 8.5p17b3 refers us to 8.5.2 and the elements of the `char` array are initialized by the successive characters of the string (8.5.2p1).

Note that gcc is fine with the copy-initialization `S s = {"xxx"};` while breaking on various forms of copy- and direct-initialization; argument passing (including to constructors), function return, and base- and member-initialization:

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"});

The last is particularly interesting as it indicates that this may be related to bug 43453.

Problem

The following example initializing a `std::array <char, N>` member in a constructor using a string literal doesn't compile on GCC 4.8 but compiles using 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; } ``` On first impression it looks like a GCC bug. I feel it should compile as we can initialize a `std::array<char, N>` directly with a string literal. For example: ``` std::array<char, 4> test = {"bug"}; //works ``` I would be interested to see what the Standard says about this.

Original source