【问题标题】:Initialization of static constexpr member array in gcc 4.8gcc 4.8中静态constexpr成员数组的初始化
【发布时间】:2015-05-29 22:36:25
【问题描述】:

以下代码在使用-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[];

但是,在 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'

顺便说一句,如果我做同样的事情,但将 bars 设为静态 const 全局数组,它在 gcc 4.8 和 clang 中编译得很好。如果我用一对额外的 {} 包围列表中的每个整数文字,它也将编译得很好。

那么这是 gcc 4.8 中的错误吗?标准说什么是合适的语法?当我省略额外的大括号时,调用了 c++11 统一初始化标准的哪一部分?

编辑:看起来标准说这应该调用聚合初始化,这应该允许“大括号省略”。因此,这似乎是 gcc 4.8 中的一个错误,已由 gcc 4.9 修复,但我对阅读该标准完全没有信心。我似乎在 gcc 的错误跟踪器中也找不到任何关于此的错误报告,所以我很容易出错。

【问题讨论】:

  • 您认为这是一个已修复的错误吗?

标签: c++ c++11 gcc constexpr uniform-initialization


【解决方案1】:

为了做你想做的事,你需要在 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[];

显然 gcc 4.8.3 不会将大括号内的值隐式转换为 Bar 对象,而 gcc 4.9.1 会。

【讨论】:

  • 当然,这就是我最终走的路线。这最终暴露了 gcc 4.9 中的另一个错误(我在这里报告:gcc.gnu.org/bugzilla/show_bug.cgi?id=65695)。但我的问题是,标准是否允许在没有这些大括号的情况下进行初始化?我认为答案是肯定的,这只是 gcc 处理带有 constexpr 成员的大括号省略中的一个错误。
  • 我不会将此称为错误。 GCC 只是要求您在声明 constexpr 变量时声明一个 constexpr 构造函数。我还查看了您的错误报告并回复了它。您想要在那里做的事情不应该工作:您不应该能够将非静态成员函数的地址存储在静态变量中。
  • GCC 4.8 声称支持 ISO/IEC 14882:2011 (c++11) 标准。如果不允许大括号省略违反了标准(我很确定确实如此),那么这是 GCC 4.8 中的一个错误。并且,类似地,该标准有一个关于常量表达式的部分。它给出了一长串不是常量表达式的东西。根据我(当然是业余的)对标准的阅读,非静态成员函数的地址是一个常量表达式。
猜你喜欢
  • 2012-07-16
  • 2018-11-11
  • 2016-10-15
  • 1970-01-01
  • 2021-08-07
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多