C++ GCC和-Wconversion

C++ GCC和-Wconversion,c++,gcc,language-lawyer,C++,Gcc,Language Lawyer,让我们编译以下程序: int main() { uint16_t data = 0; data |= uint16_t(std::round(3.14f)); return 0; } 使用g++-Wconversion prog.cpp 我们将得到警告:从'int'转换为'uint16_t{aka short unsigned int}可能会改变其值,但我在这里看不到隐式转换 此类警告应通过显式强制转换静音,例如: double d = 3.14; float foo1

让我们编译以下程序:

int main()
{
    uint16_t data = 0;
    data |= uint16_t(std::round(3.14f));
    return 0;
}
使用
g++-Wconversion prog.cpp

我们将得到
警告:从'int'转换为'uint16_t{aka short unsigned int}可能会改变其值
,但我在这里看不到隐式转换

此类警告应通过显式强制转换静音,例如:

double d = 3.14;
float foo1 = d; // Warning
float foo2 = float(d); // No warning
float foo2 = static_cast<float>(d); // No warning
double d=3.14;
float foo1=d;//警告
浮点数foo2=浮点数(d);//没有警告
float foo2=静态_cast(d);//没有警告
GCC就在这里还是一个bug

请注意,我的代码片段是最小的。例如,警告在以下情况下消失:

  • 3.14
    中删除
    f
    后缀,即使其成为
    double
  • 使用赋值代替
    |=
  • 删除
    std::round
  • 缓存舍入结果:
    const auto r=uint16_t(标准::舍入(3.14f)),然后将其分配给
    数据
GCC就在这里还是一个bug

由于行为与预期不符,我称之为bug

从中,在GCC看来,
data |=uint16_t(std::round(3.14f))
被翻译为

(无效)(数据=目标,数据非左值)

TARGET_EXPR
表示一个临时对象。
D.2364
是一个内部变量名。)

将GCC内部语言翻译成C++,得到< /P>

data = (temp = (uint16_t) round (3.14e+0), data | temp)
由于逗号表达式的LHS不影响RHS,因此这应该与
data=data | temp
一样安全。然而,GCC警告前者,而不是后者,这很可能不是故意的。因此,我认为这是GCC维护人员的疏忽。

警告是假的

根据:

对于每一个三元组(L,VQ,R),其中L是一个积分类型,VQ是易变的或空的,R是一个提升的积分类型,存在以下形式的候选算子函数

VQ L&   operator|=(VQ L&, R);
因此我们得到一个内置的
无符号短运算符|=(无符号短&,无符号int)

给定表达式中没有隐式转换

uint16_t data = 0;
data |= uint16_t(std::round(3.14f));

更简单的例子(不需要头和函数)是
短数据(0);数据|=短(浮点{3.0f})@VTT确实如此。在我的编译器上复制。