Question

const auto min = -std::numeric_limits<T>::max();
T x = min; // conversion from 'const int' to 'short', possible loss of data

T is a template argument, a short in this case. Unary minus apparently performs integral promotion.

  • Why does unary minus perform integral promotion?
  • If auto is changed to T no warning is generated, but it should be assigning an int to a short. Why isn't there a warning (it could be VS being fancy)?
Was it helpful?

Solution

Short answer: (now long because people want to be excessively pedantic about English which by its very nature is not exact).

Its not explicitly (as in the unary minus mathematical). But as part of any operation (this includes unary minus operation) on POD data there is an implicit check on input parameters (the smallest integer type that can be used in and operation is int) so there is integral promotion on the input before the unary minus (the mathematical part not the operation part). The output of all operations on POD is the same as the input parameters (after integral promotion is applied). Thus here the output is also an int.

Long answer:

In C (and thus C++) the smallest type that POD operations happen on is int. So before the unary minus is applied the value is converted to int. Then the unary minus is applied. The result of the expression is thus int.

See here: Implicit type conversion rules in C++ operators

OTHER TIPS

Unary minus performs integral promotion because all the arithmetic operators on integral types do it. This convention was probably established for performance reasons (typically int was the size best suited for integral operations on the hardware) and perhaps because it's sometimes useful not to be limited to the range of smaller integral types.

I've seen bugs where people do:

uint64_t i = 1 << 33; // use 64-bit type to ensure enough bits to hold the result

But this is a bug because the result of 1 << 33 doesn't depend on what it's assigned to. (Today we have warnings about this). The solution, which is ugly, is to manually force one of the operands to be large enough: uint64_t i = static_cast<uint64_t>(1) << 33

Integral promotion happens to avoid the same sort of bug with smaller types, which would have been the common case back when C was designed this way:

short a = 30000, b = 20000
int i = a + b;

In any case "It doesn't have to be logical. It's the law."

I think this is to account for ideal computer model, which C/C++ assume. Calculations are performed in registers and it implies result's size would be machine word. Hence "automagical" expansion

I believe it's (partly) because the negative of a short may not be representable as a short.
(-215 might need promotion to int if short is 16-bit and int is bigger.)

Of course, there's no guarantee that int is any bigger, but it's (usually?) the most optimal data type for the machine anyway, so it makes sense to try promoting it to int since there's likely no performance cost anyway.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top