Conversiones aritméticas habituales
Muchos operadores binarios que esperan operandos de tipo aritmético o enumeración provocan conversiones y producen tipos de resultados de forma similar. El objetivo es producir un tipo común, que también es el tipo del resultado. Este patrón se denomina conversiones aritméticas habituales.
Definición
Las conversiones aritméticas habituales se definen de la siguiente manera:
Etapa 1
Aplica conversión de l-valor a r-valor a ambos operandos, los pr-valores resultantes se utilizan en lugar de los operandos originales para el resto del proceso.
Etapa 2
|
(desde C++11) |
Etapa 3
|
(desde C++26) |
Etapa 4
- Si alguno de los operandos es de tipo de punto flotante, se aplican las siguientes reglas:
- Si ambos operandos tienen el mismo tipo, no se realizará ninguna conversión adicional.
- De lo contrario, si uno de los operandos es de un tipo que no es de punto flotante, ese operando se convierte al tipo del otro operando.
- De lo contrario, si los rangos de conversión de punto flotante de los tipos de los operandos están ordenados pero no son iguales, entonces el operando del tipo con el rango de conversión de punto flotante menor se convierte al tipo del otro operando.
|
(desde C++23) |
- De lo contrario, ambos operandos son de tipo entero, se procede a la siguiente etapa.
Etapa 5
Ambos operandos se convierten a un tipo común C. Dados los tipos T1 y T2 como el tipo promocionado (según las reglas de promociones de enteros) de los operandos, se aplican las siguientes reglas para determinar C:
- Si
T1yT2son del mismo tipo,Ces ese tipo. - De lo contrario, si
T1yT2son ambos de tipo entero con signo o ambos de tipo entero sin signo,Ces el tipo de rango de conversión de enteros mayor. - De lo contrario, un tipo entre
T1yT2es un tipo de entero con signoS, el otro tipo es un tipo entero sin signoU. Se aplican las siguientes reglas:
- Si el rango de conversión de enteros de
Ues mayor o igual que el rango de conversión de enteros deS,CesU. - De lo contrario, si
Spuede representar todos los valores deU,CesS. - De lo contrario,
Ces el tipo entero sin signo correspondiente aS.
- Si el rango de conversión de enteros de
|
Si un operando es de tipo enumeración y el otro operando es de un tipo enumeración diferente o un tipo de punto flotante, este comportamiento queda obsoleto. |
(desde C++20) (hasta C++26) |
Rango de conversión de enteros
Cada tipo entero tiene un rango de conversión de enteros definido de la siguiente manera:
- No hay dos tipos enteros con signo distintos de
charysigned char(sichartiene signo) que tengan el mismo rango, incluso si tienen la misma representación. - El rango de un tipo entero con signo es mayor que el rango de cualquier tipo entero con signo con un ancho menor.
- Los rangos de los siguientes tipos enteros disminuyen en orden:
|
(desde C++11) |
longintshortsigned char
- El rango de cualquier tipo entero sin signo es igual al rango del tipo entero con signo correspondiente.
|
(desde C++11) |
- El rango de
booles menor que el rango de todos los tipos enteros estándar. - Los rangos de los tipos de caracteres codificados (
char,char8_t(desde C++20),char16_t,char32_t, (desde C++11) ywchar_t) son iguales a los rangos de sus tipos subyacentes, lo que significa:
- El rango de
chares igual al rango designed charyunsigned char.
- El rango de
|
(desde C++20) |
|
(desde C++11) |
- El rango de
wchar_tes igual al rango de su tipo subyacente definido por la implementación.
- El rango de
|
(desde C++11) |
- Para todos los tipos enteros
T1,T2yT3, siT1tiene mayor rango queT2yT2tiene mayor rango queT3, entoncesT1tiene mayor rango queT3.
El rango de conversión de enteros también se utiliza en la definición de la promoción de enteros.
Rango y subrango de conversión de punto flotante
Rango de conversión de punto flotante
Cada tipo de punto flotante tiene un rango de conversión de punto flotante definido de la siguiente manera:
- Los rangos de los tipos de punto flotante estándar disminuyen en orden:
long doubledoublefloat
|
(desde C++23) |
Subrango de conversión de punto flotanteLos tipos de punto flotante que tienen rangos de conversión de punto flotante iguales se ordenan por subrango de conversión de punto flotante. El subrango forma un orden total entre los tipos con rangos iguales. Los tipos |
(desde C++23) |
Uso
El rango y subrango de conversión de punto flotante también se utilizan para
- determinar si una conversión entre diferentes tipos de punto flotante puede ser implícita o es una conversión estrechante,
- distinguir las secuencias de conversión en la resolución de sobrecarga,
|
- determinar si el constructor de conversión de std::complex es explícito, o
- determinar el tipo de punto flotante común si los argumentos de diferentes tipos de punto flotante se pasan a funciones matemáticas comunes o especiales.
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 1642 | C++98 | Las conversiones aritméticas habituales pueden involucrar l-valores. | Aplica primero las conversiones de l-valor a r-valor. |
| CWG 2528 | C++20 | La comparación de tres vías entre unsigned chary unsigned int está mal formada debido ala promoción de enteros intermedia.[1] |
Determina el tipo común basado en los tipos promocionados, sin promocionar realmente los operandos.[2] |
| CWG 2892 | C++98 | Cuando ambos operandos son del mismo tipo de punto flotante, el significado de “no se necesita ninguna conversión adicional” no estaba claro. |
Se cambió a “no se realizará ninguna conversión adicional”. |
- ↑ Antes de la resolución,
unsigned charse promueve aintal comienzo de la etapa 5, luego se convierte aunsigned int. Sin embargo, la última conversión es restrictiva, lo que hace que la comparación de tres vías esté mal formada. - ↑ Después de la resolución, el tipo común sigue siendo
unsigned int. La diferencia es queunsigned charse convierte directamente enunsigned intsin la promoción de enteros intermedia. La conversión no es restrictiva y, por lo tanto, la comparación de tres vías está bien formada.