Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialization of static constexpr member array in gcc 4.8

The following code compiles and runs in gcc 4.9.1 and clang-3.6 when using -std=c++11:

struct Bar
{
    int x;
};

struct Foo
{
    static constexpr Bar bars[] = {1, 2, 3};
};

constexpr Bar Foo::bars[];

However, it fails in gcc 4.8.3, resulting in the error message

./cpptest.cpp:14:43: error: could not convert '1' from 'int' to 'const Bar'
     static constexpr Bar bars[] = {1, 2, 3};
                                           ^
./cpptest.cpp:14:43: error: could not convert '2' from 'int' to 'const Bar'
./cpptest.cpp:14:43: error: could not convert '3' from 'int' to 'const Bar'

Incidentally, if I do the same thing but make bars a static const global array, it compiles fine in gcc 4.8 and clang. It will also compile just fine if I surround each of the integer literals in the list with an extra pair of {}.

So is this a bug in gcc 4.8? What does the standard say is the appropriate syntax for this? What part of the c++11 uniform initialization standard is being invoked when I omit the extra braces?

Edit: It looks like the standard says that this should invoke aggregate initialization, which should allow for "brace elision". So it seems it's a bug in gcc 4.8, that was fixed by gcc 4.9, but I'm not at all confident in my reading of the standard. I also can't seem to find any bug report in gcc's bug tracker regarding this, so I could easily be wrong.

like image 451
Bobby Moretti Avatar asked Mar 26 '15 01:03

Bobby Moretti


1 Answers

In order to do what you want to do, you need specify a constexpr constructor inside Foo:

struct Bar
{
    constexpr Bar(int c) : x(c)
    {}

    int x;
};

struct Foo
{
    static constexpr Bar bars[] = {1, 2, 3};
};

constexpr Bar Foo::bars[];

Apparently gcc 4.8.3 doesn't implicity convert the values inside the curly brackets to Bar objects, while gcc 4.9.1 does.

like image 78
kamshi Avatar answered Oct 07 '22 21:10

kamshi