Bob*_*tti 7 c++ gcc uniform-initialization constexpr c++11
使用-std = c ++ 11时,以下代码在gcc 4.9.1和clang-3.6中编译和运行:
struct Bar
{
int x;
};
struct Foo
{
static constexpr Bar bars[] = {1, 2, 3};
};
constexpr Bar Foo::bars[];
Run Code Online (Sandbox Code Playgroud)
但是,它在gcc 4.8.3中失败,导致错误消息
./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'
Run Code Online (Sandbox Code Playgroud)
顺便说一下,如果我做同样的事情但是创建bars一个静态const全局数组,它在gcc 4.8和clang中编译得很好.如果我用额外的一对包围列表中的每个整数文字,它也会编译得很好{}.
这是gcc 4.8中的一个错误吗?标准所说的是适当的语法?当我省略额外的括号时,调用c ++ 11统一初始化标准的哪一部分?
编辑:看起来标准说这应该调用聚合初始化,这应该允许"支持elision".所以它似乎是gcc 4.8中的一个错误,这是由gcc 4.9修复的,但我对阅读标准并不是很有信心.我也似乎无法在gcc的bug追踪器中发现任何有关此问题的错误报告,所以我很容易出错.
为了做你想做的事,你需要在 Foo 中指定一个 constexpr 构造函数:
struct Bar
{
constexpr Bar(int c) : x(c)
{}
int x;
};
struct Foo
{
static constexpr Bar bars[] = {1, 2, 3};
};
constexpr Bar Foo::bars[];
Run Code Online (Sandbox Code Playgroud)
显然,gcc 4.8.3 不会将大括号内的值隐式转换为 Bar 对象,而 gcc 4.9.1 会这样做。