[英]GCC, clang disagree with MSVC on narrowing conversion
Consider the following program:考虑以下程序:
struct uint1 {
unsigned x;
uint1(unsigned x_) : x(x_) { }
};
struct foo { uint1 a; };
foo f(int v) {
return {v};
}
struct bar { unsigned a; };
bar g(int v) {
return {v};
}
Now, where do we have narrowing conversions here?现在,我们在哪里缩小转换?
Compiler![]() |
version![]() |
narrowing conversion in f() ?![]() f() 中的转换? |
narrowing conversion in g() ?![]() g() 中的转换? |
---|---|---|---|
GCC ![]() |
11.2 ![]() |
No![]() |
Yes![]() |
clang ![]() |
13.0 ![]() |
No![]() |
Yes![]() |
MSVC ![]() |
19.4 ![]() |
Yes![]() |
Yes![]() |
Which is right?哪个是对的? Naively, it seems to me there's a narrowing conversion in both functions.
天真地,在我看来,这两个功能的转换都在缩小。
See it all on GodBolt .在GodBolt上查看所有内容。
Note: C++17 in case it matters.注意:C++17 以防万一。
It seems that GCC and Clang are right in not classing this as a narrowing conversion.似乎 GCC 和 Clang 没有将其归类为缩小转换是正确的。
The initialisation in question is that of a foo
object.有问题的初始化是
foo
object 的初始化。 Its constructor argument is enclosed in {}
.它的构造函数参数包含在
{}
中。 There cannot be a narrowing conversion in this initialisation, because the argument of the constructor is not of a numeric type.在这个初始化中不能有缩小转换,因为构造函数的参数不是数字类型。 It is
struct uint1
.它是
struct uint1
。
So where does struct uint1
cone from?那么
struct uint1
cone 是从哪里来的呢? It is converted from v
, but not by means of braced initialisation.它是从
v
转换而来的,但不是通过大括号初始化。 The pair of braces around v
is already occupied by the constructor of uint1
. v
周围的一对花括号已经被uint1
的构造函数占用。
So this is equivalent to foo{uint1(v)}
.所以这相当于
foo{uint1(v)}
。
MSVC on the other hand seems to interpret this as foo(uint1{v})
, and I don't think this interpretation is justified.另一方面,MSVC 似乎将此解释为
foo(uint1{v})
,我认为这种解释是不合理的。
Neither compiler complains about an explicit foo{uint1(v)}
, as is required by the standard, because there is no narrowing at the top level.两个编译器都没有抱怨标准要求的显式
foo{uint1(v)}
,因为在顶层没有缩小范围。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.