Why does the following expression indicate a narrowing of the conversion?

This expression can be found in the example in clause 8.5.4 / 7 in the standard (N3797)

unsigned int ui1 = {-1}; // error: narrows 

Given §8.5.4 / 7 and its fourth marker point:

Narrowing a transform is an implicit transform:

  • from an integer type or an non-enumerated enumeration type to an integer type that cannot represent all the values ​​of the source type, except when the source is a constant expression, the value of which after the integral promotions will fit into the target type.

I would say that there is no narrowing, since -1 is a constant expression, the value of which, after whole advertising, fits into an unsigned int.

See also §4.5 / 1 on Integral Promotion :

A value of an integer type other than bool, char16_t, char32_t or wchar_t, whose integer conversion rank (4.13) is less than the rank of int can be converted to prvalue of type int if int can represent all values ​​of the source type; otherwise, the original value may be converted to a prvalue of type unsigned int.

From 4.13 we have that rank -1 (an int) is equal to rank unsigned int and therefore can be converted to unsigned int.

Edit

Unfortunately, Jerry Coffin removed his answer from this thread. I believe that he was on the right track, if we agree that the current reading of the fourth marker point in § 8.5.5 / 7 is incorrect, then change it in the standard.

+8
c ++ language-lawyer c ++ 11
source share
3 answers

The change in the wording of the standard is intended to confirm the understanding that the conversion of a negative value to an unsigned type is and has always been a narrowing conversion.

Unofficially, -1 cannot be represented in the range of any unsigned type, and the bit pattern that represents it does not represent the same value if it is stored in an unsigned int. Therefore, this narrowing of conversion and promotion / expansion is not involved.

This is about the exquisite art of reading the standard. As usual, the compiler knows better.

+1
source share

There is no solid advertising from int to unsigned int , so it is still unformatted.

It will be an integral transformation .

+7
source share

A narrowing is an implicit conversion from an integer type to an integer type that cannot represent all the values ​​of the original type

Converting from an integer int to an integer unsigned int , of course, cannot represent all the values ​​of the original type - the standard here is pretty straightforward. If you really need it, you can do

  unsigned int ui1 = {-1u}; 

This works without errors / warnings, since 1u is a literal of type unsigned int , which is then canceled. This is well defined as [expr.unary.op] in standard states:

The negation of the unsigned value is calculated by subtracting its value from 2 n where n is the number of bits in the advanced operand.

-1 however, is an int before and after negation, and therefore becomes a narrowing transformation. No negative literals ; see this answer for more details.

Advancement informally copies the same value into a larger space, so it should not be confused, since the sizes ( signed and unsigned ) are equal. Even if you try to convert it to some larger size, say unsigned long long , it still narrows the conversion, since it cannot really represent a negative number.

+1
source share

All Articles