uniform initialization issues

This code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main()
{
   unsigned short width { 5 };
   unsigned short length { 10 };

   // the following errors out when using uniform initialization
   unsigned short area { width * length };

   std::cout << "width:  " << width << "\n";
   std::cout << "length: " << length << "\n";
   std::cout << "area:   " << area << "\n";
}

error in VS2019 and Code::Blocks. VS error:
Error C2397 conversion from 'int' to 'unsigned short' requires a narrowing conversion Project1 D:\Programming\Projects 2019\cplusplus2019\Project1\Source1.cpp 9


unsigned char produces the same error.

Declare the variables as signed short or char, and no problems with narrowing. Same for ints, longs or long longs, signed or unsigned.

Weird. Would this be a defect in VS/CB, or something not addressed in the standard?

Or am I just expecting too much?
Last edited on
All the binary operators convert their operands to ints or bigger, except right- and left- bitshifts.

Each operand undergoes integral promotion, performed as part of the usual arithmetic conversions. The type of the expression width * length is int, which won't narrow to unsigned short inside braces.

The usual arithmetic conversions occur for operands of binary multiplication:
http://eel.is/c++draft/expr.arith.conv#1.5

Integral promotion of each operand occurs as part of the usual arithmetic conversions:
http://eel.is/c++draft/expr#conv.prom

And integral promotion of unsigned short (or a short, or char, etc.) yields int.
http://eel.is/c++draft/expr#conv.prom

Declare the variables as signed short or char, and no problems with narrowing. Same for ints, longs or long longs, signed or unsigned.

This seems strange: show an example?
Last edited on
mbozzi wrote:
This seems strange: show an example?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

int main()
{
   short width { 5 };
   short length { 10 };

   short area { width * length };

   std::cout << "width:  " << width << "\n";
   std::cout << "length: " << length << "\n";
   std::cout << "area:   " << area << "\n";
}

No warning or error from VS2019. Code::Blocks spits out a warning, only when doing a full rebuild:

D:\Programming\Projects\CBTest\main.cpp|8|warning: narrowing conversion of '(((int)width) * ((int)length))' from 'int' to 'short unsigned int' inside { } [-Wnarrowing]|


mbozzi wrote:
All the binary operators convert their operands to ints or bigger, except right- and left- bitshifts.

Each operand undergoes integral promotion, performed as part of the usual arithmetic conversions. The type of the expression width * length is int, which won't narrow to unsigned short inside braces.

Now THAT makes sense, in conjunction with the warning from C::B. VS is not completely following the standard. Weird that unsigned short/char gives VS heartburn, but not (signed) short/char.
Here's what GCC and Clang have to say about it on Coliru (both compilers emit errors):
http://coliru.stacked-crooked.com/a/48931e2f78f0592f

It must be that VS2019 is noncompliant.
Last edited on
It must be that VS2019 is noncompliant.

I'd have to say that is an understatement. ;)
Topic archived. No new replies allowed.