简体   繁体   中英

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() ? 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM