让我们编译以下程序:
int main()
{
uint16_t data = 0;
data |= uint16_t(std::round(3.14f));
return 0;
}
与g++ -Wconversion prog.cpp
我们会得到warning: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value
,但在这里看不到隐式转换。
此类警告应通过显式强制转换忽略,例如:
double d = 3.14;
float foo1 = d; // Warning
float foo2 = float(d); // No warning
float foo2 = static_cast<float>(d); // No warning
GCC在这里还是一个错误?
请注意,我的代码段很小。例如,在以下情况下警告会消失:
f
中删除3.14
后缀,即设为double
|=
std::round
const auto r = uint16_t(std::round(3.14f));
,然后将其或分配给data
。答案 0 :(得分:1)
GCC在这里还是一个错误?
由于行为与预期不符,因此我将其称为错误。
从https://godbolt.org/z/aSj--7看来,在海湾合作委员会看来,data |= uint16_t(std::round(3.14f))
被翻译为
(void) (data = TARGET_EXPR <D.2364, (uint16_t) round (3.1400001049041748046875e+0)>;, data | NON_LVALUE_EXPR <D.2364>;)
({TARGET_EXPR
代表一个临时对象。D.2364
是一个内部变量名。)
将GCC的内部语言翻译回C ++,我们将得到
data = (temp = (uint16_t) round (3.14e+0), data | temp)
由于逗号表达式的LHS不会影响RHS,因此它应与data = data | temp
一样安全。但是,海湾合作委员会警告前者,但不警告后者,这不太可能是故意的。因此,我认为这是对GCC维护者的疏忽。
答案 1 :(得分:1)
The warning is bogus.
According to [over.built]/22:
For every triple (L, VQ, R), where L is an integral type, VQ is either volatile or empty, and R is a promoted integral type, there exist candidate operator functions of the form ...
VQ L& operator|=(VQ L&, R);
So we get a built-in unsigned short operator |=(unsigned short&, unsigned int);
There are no implicit conversions in the given expression
uint16_t data = 0;
data |= uint16_t(std::round(3.14f));