1

I'm learning C++ and have run into something I'd like to know more about.

Say I try to declare and initialize an array as:

int myarray[] = {1, 2, 3, 4.1};

Note the non-integer 4.1 at index 3. In Visual Studio, this will compile with a warning, but in gcc it will fail to compile. Does the standard (for 11, 14, or 17) have anything to say about automatic conversion when assigning the wrong type to an element of an array, or is it left to the compiler to decide what happens (or something else)? I'd like to find out why the results are different.

bolov
  • 72,283
  • 15
  • 145
  • 224
Cpyreey
  • 13
  • 2
  • 1
    This is a [narrowing conversion](https://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin) and is illegal in C++11 and later – Ryan Haining Aug 23 '18 at 23:26

1 Answers1

2

Pre C++11 the code was legal. Since C++11 that is considered a narrow conversion (from double to int there is information loss) and is illegal.

What compiler and what version of compiler you use matters. Visual Studio, especially slightly older versions don't actually implement any standard in full. They implements bits of C++11, bits of C++14, bits of C++17. With the newest versions that could have possibly changed, I haven't followed it's evolution lately.

Really older versions of gcc default to gnu++98 which is C++98 with gnu extensions, while newer version default to gnu++11 and gnu++14. For your curiosity if you want to see it working in gcc use -std=c++98 and you will only get a warning.


In hindsight we have learned that allowing implicit conversions that can lose information (e.g. from floating point to integer, from long long to int) was not a good ideea. With C++11 this was taken into consideration. Making all such implicit conversions illegal was deemed to much of a breaking change. The introduction of list initialization offered a middle ground: disallow narrowing conversions only in a list initialization and recommend using list initialization as de facto way of initializing an object. The downside was that it was a breaking change for array initialization, but the benefits were weighted to be of more value.

int a = 2.4;   // still allowed, but not recommended
int a(2.4);    // still allowed, but not recommended

int a = {2.4}; // New way to initialize. Narrowing conversion, illegal
int a{2.4};    // New and recommended way to initialize. Narrowing conversion, illegal

You can read more about narrow conversions here: https://en.cppreference.com/w/cpp/language/list_initialization

bolov
  • 72,283
  • 15
  • 145
  • 224