this is much like this question Why must a short be converted to an int before arithmetic operations in C and C++? however there is a sub-question why the compiler diagnoses a warning in one case and an error in the other case ,with the exact same expression.
I really like the use of the auto
'type' as in auto var =
..., but MSVC 2015 CTP gives an error from my code.
The issue is I am auto
-ing an expression of type short
but sometimes it's promoted to int
.
Here's a MCVE:
struct MY_COORD { short X; short Y; };
using t_crd = MY_COORD;
void call_test ( t_crd x ) {}
int main()
{
t_crd crd { 10 ,20 };
auto x5 = crd.X - crd.Y;
auto y5 = crd.Y - crd.X;
t_crd crd5 { x5 ,y5 }; // (1)
call_test( t_crd{ x5 ,y5 } ); // (2)
}
The messages from lines (1) and (2) are respectively:
warning C4838: conversion from 'int' to 'short' requires a narrowing conversion
error C2397: conversion from 'int' to 'short' requires a narrowing conversion
I thought this code was OK but it's not according to MSVC 2015 CTP compiler (but Intellisense doesn't indicate it). Is there some obscure little rule that I missed that makes MSVC right ?
And if so why is the same expression a warning in one case and an error in the other case ?
I wanted to use it in the initialization of a loop variable like this:
MY_COORD pos = ResultFromFunction();
auto rows = pos.Y;
for ( auto i = (rows - rows); i < rows; ++i )
{
coord c{ 0 ,i };
...
}
Arithmetic operators always promote integral types smaller than int
to int
before performing the operation. This is mandated in [expr]/10
of the C++11 standard:
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions.
The sub-clause from there which applies to your case specifies that the operands in rows - rows
will be subjected to integral promotion. In particular, according to [conv.prom]/1
A prvalue of an integer type other than
bool
,char16_t
,char32_t
, orwchar_t
whose integer conversion rank is less than the rank ofint
can be converted to a prvalue of typeint
ifint
can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of typeunsigned int
.
Since the rank of short
is guaranteed to be less than the rank of int
, both the operands of rows - rows
are promoted to int
, giving the expression rows - rows
a type of int
.
About the narrowing conversion, the standard specifies(in [dcl.init.aggr]
) that, in aggregate initialization, if the expression requires a narrowing conversion, the program is ill-formed. Compilers are free to diagnose it anyway they like. IIRC, under the simple circumstances like t_crd crd5 { x5 ,y5 };
, clang 3.5 issues an error while g++ 4.9.2 issues a warning when used with the default warnings settings. Either way. MSVC's behaviour, even if slightly odd, is standard-conforming.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With