Reputation: 717
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.
Upvotes: 7
Views: 1453
Reputation: 615
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.
Upvotes: 2