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() ? |
narrowing conversion in 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 .
Note: C++17 in case it matters.
It seems that GCC and Clang are right in not classing this as a narrowing conversion.
The initialisation in question is that of a 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
.
So where does struct uint1
cone from? It is converted from v
, but not by means of braced initialisation. The pair of braces around v
is already occupied by the constructor of uint1
.
So this is equivalent to 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.
Neither compiler complains about an explicit foo{uint1(v)}
, as is required by the standard, because there is no narrowing at the top level.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.