Boost logo

Boost :

Subject: Re: [boost] [mpl] clang error for narrowing from unsigned int 0xffffffff to long
From: Jonathan Wakely (jwakely.boost_at_[hidden])
Date: 2013-11-14 05:02:22


On 14 November 2013 05:17, Gavin Lambert wrote:
> On 14/11/2013 17:22, Quoth Edward Diener:
>
>> Or my own preference of 'static_cast<long>(0xffffffff)'. But using
>> '0xffffffffL' does not work. I admit that understanding the C++
>> Standard's different interprtetation of these two forms is beyond me.
>
>
> 0xffffffffL is an invalid literal value because it is out of range for the
> "long" type. (Using UL or even just U would make it valid, but still not
> the type you wanted.)

It's not invalid, it has the value 4294967295 and a type according to
Table 6 in 2.14.2 [lex.icon]. For 32-bit targets it has type unsigned
long because 4294967295 doesn't fit in a 32-bit long, and when
converted to long it is still a narrowing conversion because the value
changes.

> 0xffffffff does not explicitly specify a size so the compiler is allowed to
> pick one itself; it will probably infer "unsigned int", as "signed int" is
> too small. (Or on platforms where "int" is 16-bit, it would infer "unsigned
> long".)

The compiler doesn't get to pick, again Table 6 says what its type is.

> An explicit cast on an integer is allowed to reinterpret unsigned to/from
> signed and/or extend or truncate bits, through long historic usage in C
> code.

And a type cast is not a context where narrowing conversions are
forbidden. The point of introducing narrowing conversions into C++11
was to close some of the holes in the C types system that allow
silent, value-changing conversions, but for backwards compatibility to
only prevent them in some contexts, e.g. using the new C++11
braced-init syntax or in "converted constant expressions" (as used for
non-type template arguments of integral type, see 14.3.2
[temp.arg.nontype] p5.)

> (Technically that usage should ideally require reinterpret_cast instead of
> static_cast, since you're reinterpreting the sign bit. But again I think
> tradition won out here -- and it's a less scary conversion than other places
> you need reinterpret_cast.)

No, reinterpret_cast between different integer types is ill-formed.
Only the conversions listed in [expr.reinterpret.cast] are allowed.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk