$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [mpl] clang error for narrowing from unsigned int 0xffffffff to long
From: Edward Diener (eldiener_at_[hidden])
Date: 2013-11-14 19:04:50
On 11/14/2013 6:41 PM, Gavin Lambert wrote:
> On 14/11/2013 23:02, Quoth Jonathan Wakely:
>>> 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.
>
> That counts as the compiler picking the type, because on different
> platforms a different result occurs, and it has a wider range to choose
> from without the suffix. As I said, on 16-bit platforms it would pick
> "unsigned long" and on 32-bit platforms it would pick "unsigned int".
>
>>> (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.
>
> I know that, that wasn't my point. I wasn't saying that
> reinterpret_cast is valid according to the standard, I was saying that
> the internalised meaning of reinterpret_cast in most people's heads
> ("interpret the underlying raw bit storage of this variable as this
> other type") is closer in behaviour to what static_cast on a same-size
> integer type actually does (at least in most implementations), vs. what
> static_cast does when performing any other conversion (eg. integer to
> float alters the bit pattern, pointer to other pointer might return a
> different pointer value, etc).
>
> I'm not even saying that this is wrong -- part of the reason to make the
> cast types explicit over the C-style casts was to more clearly call out
> the places where you're doing "scary" things (aka reinterpret_cast), to
> enhance type safety and stamp out void* -- and integer conversions
> aren't sufficiently scary (although arguably they're still something you
> need to pay almost as much attention to -- while they're less likely to
> crash or UB if used wrong than bad pointer casts, they can still produce
> incorrect results).
>
> (And I might be wrong about this [as I haven't looked at C++11 changes
> in detail] but IIRC the standard does not actually guarantee that ints
> are in two's-complement form, so the integer static_cast might not be
> reversible, although I think a lot of code assumes it is.)
I think that you are right that the standard says nothing about two's
complement notation. It does seem a pretty safe bet that the cast is
reversible between 'unsigned int' and 'long' since the 'long' is
guaranteed to be at least the size in bits of the 'unsigned int'.