Implementation-defined narrowing conversions?
Asked Answered
A

2

12

C++11 formalized the notion of a narrowing conversion, and disallowed using one at the top level in list-initialization.

I am wondering whether, given two types T and U, it is possible for it to be implementation-defined whether a conversion from T to U is narrowing. According to my reading of the standard, this is the case. Here is my reasoning:

  • According to dcl.init.list (8.5.4) paragraph 7, one way a conversion can be narrowing is if it's an implicit conversion "from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type".
  • Consider an implicit conversion from unsigned int to long.
  • Regarding the relative sizes of int and long, C++ requires only that sizeof(int) <= sizeof(long).
  • Consider an implementation A, where sizeof(int) == sizeof(long). On this implementation, long cannot represent all the values of unsigned int, so the conversion would be narrowing.
  • Consider an implementation B, where sizeof(int) < sizeof(long). On this implementation, long can represent all the values of unsigned int, so the conversion would not be narrowing.

Am I correct in my analysis that it can be implementation-defined whether a conversion is narrowing? Is this desirable?

Agon answered 19/11, 2012 at 10:14 Comment(0)
C
5

I would indeed prefer the "narrowing conversion" to be defined on the types itself. In a way so that int i{long(non_constant_expression)} is never allowed to compile. The simple reason is: Either you don't need the long range, then you should use int in the first place, or you really want the "cut", which seems like a rare enough case for me to require an explicit type conversion or a cast. To answer the first question: It is implementation defined.

But to be honest, I almost never use this raw types, just size_t, int32_t, uint16_t etc., and this solves the problem automatically. (uint16_t {uint8_t()} is always narrowing, uint16_t{uint16_t()} never.) One just has to thoughtfully convert size_t into something else, but that is always the case.

Cultus answered 19/11, 2012 at 11:49 Comment(1)
Bad example: int i{long(5)} is never a narrowing conversion. 5 is a literal, and its value will fit in an int, so the compiler is required to allow it.Disinherit
C
0

În my case, for this piece of code: char *pointer = strchr(s1, s2[I]); int start = pointer - s1; It worked to change the int data type to long: long start = pointer - s1;

"The compiler cannot determine how large or small a value is for a specific data type; therefore, the compiler cannot determine if the specified value fits in the new field that you assign it to. If you are sure that there is no overflow, explicitly type cast the value to avoid the warning." - source : https://www.ibm.com/docs/en/ztpf/2020?topic=warnings-narrowing-conversion

Calorimeter answered 23/4, 2023 at 20:19 Comment(1)
This doesn't answer the question, it just shows how you might fix an instance of a potential narrowing conversion.Agon

© 2022 - 2024 — McMap. All rights reserved.