tipos static_cast datos conversion c++ c++11 type-conversion language-lawyer narrowing

c++ - static_cast - ¿Por qué "unsigned int ui={-1};" un error de conversión de reducción?



conversion de tipos de datos en c++ (1)

Seguramente -1, hay un entero constante y, si se convierte en unsigned y back, todavía produce int -1?

Esto está mal. Si convierte -1 a unsigned obtendrá UINT_MAX . Esto está bien porque la conversión a tipos sin firmar siempre está definida. Sin embargo, UINT_MAX no cabe en int y las conversiones a los tipos firmados solo están definidas por el estándar cuando el valor se ajusta al tipo de destino.

El Estándar en § 8.5.4 / 7 explica qué es una conversión de reducción :

Una conversión de reducción es una conversión implícita

- desde un tipo de punto flotante a un tipo entero, o

- de doble largo a doble o flotante, o de doble a flotante, excepto cuando la fuente es una expresión constante y el valor real después de la conversión está dentro del rango de valores que se pueden representar (incluso si no se puede representar exactamente), o

- desde un tipo de enteros o un tipo de enumeración sin cobertura hasta un tipo de coma flotante, excepto cuando el origen sea una expresión constante y el valor real después de la conversión se ajuste al tipo de destino y produzca el valor original cuando se vuelva a convertir al tipo original. o

- desde un tipo entero o un tipo de enumeración no codificado a un tipo entero que no puede representar todos los valores del tipo original, excepto cuando el origen es una expresión constante y el valor real después de la conversión se ajustará al tipo objetivo y generará el valor original cuando se convierte de nuevo al tipo original.

Luego, no permite dichas conversiones en algunos contextos de inicialización de listas, dando ejemplos:

[Nota: como se indicó anteriormente, dichas conversiones no están permitidas en el nivel superior en las inicializaciones de listas. - nota final] [Ejemplo:

int x = 999; // x is not a constant expression const int y = 999; const int z = 99; char c1 = x; // OK, though it might narrow (in this case, it does narrow) char c2{x}; // error: might narrow char c3{y}; // error: narrows (assuming char is 8 bits) char c4{z}; // OK: no narrowing needed unsigned char uc1 = {5}; // OK: no narrowing needed unsigned char uc2 = {-1}; // error: narrows unsigned int ui1 = {-1}; // error: narrows signed int si1 = { (unsigned int)-1 }; // error: narrows int ii = {2.0}; // error: narrows float f1 { x }; // error: might narrow float f2 { 7 }; // OK: 7 can be exactly represented as a float int f(int); int a[] = { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level

- ejemplo final]

Los 7 errores ilustrados por los ejemplos se informan como tales por clang 3.2 / 3.3 con -std=c++11 , por ejemplo

error: non-constant-expression cannot be narrowed from type ''int'' to ''char'' in initializer list [-Wc++11-narrowing]

Ninguno de ellos se informa como errores por gcc 4.7.2 / 4.8.1, pero en cada caso se da una advertencia similar, por ej.

warning: narrowing conversion of ‘x’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

(Por lo tanto, gcc parece saber lo que exige el cumplimiento, pero opta por tolerar el incumplimiento por defecto).

Lo que no entiendo es cómo el ejemplo:

unsigned int ui1 = {-1}; // error: narrows

califica como un ejemplo. (Igualmente con el ejemplo si1 simétrico.) Evidentemente, las únicas palabras con las que podría calificarse como ejemplo son las del cuarto y último ítem en la definición de conversión de estrechamiento dada anteriormente; pero si es así, ¿por qué el ejemplo no escapa por la calificación, excepto cuando la fuente es una expresión constante y el valor real después de la conversión encajará en el tipo objetivo y producirá el valor original cuando se vuelva a convertir al tipo original ? Seguramente -1 hay un entero constante y, si se convierte en unsigned y back, todavía produce int -1 ?

¿Qué me estoy perdiendo?