4

我有这段代码可以编译

#include <bitset>

struct A{
    std::bitset<50> b; };

void test(A a){
    static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
    int x = 5;
    a.b = x; }

int main(){
    A a;
    test(a); }

但这并不

#include <bitset>

struct A{
    std::bitset<50> b;
};

void test(A& a){
    static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
    int x = 5;
    a.b = x;
}

int main(){
    A a;
    test(a);
}

失败并出现此错误

const.cpp: In function ‘void test(A&)’: const.cpp:8:5: error: non-constant condition for static assertion
     static_assert(sizeof(int)*8 < a.b.size(), "can't accomodate int in bitset");
const.cpp:8:5: error: ‘a’ is not a constant expression

为什么a.b.size()在第二种情况下不被视为 constexpr ?是不是应该根据参考被视为 const 的constexpr那个?还是在第二种情况下传递的非常量引用会触发编译器生成错误?std::bitset::size()

编译器版本:Ubuntu 14.0.4 上的 g++ 4.8.4,编译时使用g++ const.cpp -std=c++1y

4

2 回答 2

3

A& a不能在常量表达式中使用,从而使您的程序格式错误。

禁止作为 a 的常量表达式的规则a.b.size()如下:aA&

[expr.const]/3

如果变量是constexpr 变量,或者它是引用类型或 const 限定的整数或枚举类型,并且它的初始化程序是常量初始化程序,则变量在遇到其初始化声明后可用于常量表达式。

在您的情况下,变量a是:

  • 未声明constexpr(作为函数参数,没有意义),
  • 并且不是整数或枚举类型,
  • 并且不是其初始化是常量初始化器的引用:

[expr.const]/2

变量或临时对象的常量初始化器o是将其完整表达式解释为常量表达式导致常量表达式的初始化器,除非 ifo是一个对象,这样的初始化器还可以调用 constexpr 构造函数o及其子对象,甚至如果这些对象是非文字类类型。


采取以下简化示例:

struct s { constexpr static bool true_value() { return true; } };
void assert_on(s const& ref)
{
    static_assert(ref.true_value());
}

int main()
{
    assert_on(s{});
}

gcc-9 错误地接受它1,但 clang-8 产生正确的诊断:

error: static_assert expression is not an integral constant expression

完整演示:https ://godbolt.org/z/t_-Ubj


1)这是GCC 错误 #66477,从 5.1 版开始生效,尚未解决。

于 2019-07-25T09:06:10.370 回答
2

使用其他人的指针1,它似乎是 gcc 和 clang 中的编译器错误。它已在 gcc 5.1 中修复,但截至 2019 年 7 月 25 日,仍然是 clang 8.0 中的错误

这是 gcc 的一个错误,在 5.1 版本中引入。见其他答案。


1)

似乎是一个(现已修复)编译器错误,因为它符合最新的 gcc 版本:https ://godbolt.org/z/ZaDXED

于 2019-07-25T07:58:03.020 回答