Namespaces
Variants

Usual arithmetic conversions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Muchos operadores binarios que esperan operandos de tipo aritmético o enumeración provocan conversiones y producen tipos de resultado de manera similar. El propósito es producir un tipo común, que también es el tipo del resultado. Este patrón se denomina conversiones aritméticas usuales .

Contenidos

Definición

Las conversiones aritméticas usuales se definen de la siguiente manera:

Etapa 1

Aplica lvalue-to-rvalue conversion a ambos operandos, los prvalues resultantes se utilizan en lugar de los operandos originales para el proceso restante.

Etapa 2

  • Si alguno de los operandos es de tipo enumeración con ámbito , no se realizan conversiones; si el otro operando no tiene el mismo tipo, la expresión está mal formada.
  • De lo contrario, proceda a la siguiente etapa.
(desde C++11)

Etapa 3

  • Si alguno de los operandos es de tipo enumeración , y el otro operando es de un tipo de enumeración diferente o un tipo de punto flotante, la expresión está mal formada.
  • De lo contrario, proceda a la siguiente etapa.
(desde C++26)

Etapa 4

  • Si alguno de los operandos es de tipo floating-point , 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 no 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 (since C++23) no son iguales, entonces el operando del tipo con el menor rango de conversión de punto flotante 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 son iguales, entonces el operando con el menor subrango de conversión de punto flotante se convierte al tipo del otro operando.
  • De lo contrario, la expresión está mal formada.
(desde C++23)
  • De lo contrario, si ambos operandos son de tipos enteros, proceda 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 promovido ( bajo las reglas de promociones integrales ) de los operandos, se aplican las siguientes reglas para determinar C :

  • Si T1 y T2 son del mismo tipo, C es ese tipo.
  • De lo contrario, si T1 y T2 son ambos tipos enteros con signo o ambos tipos enteros sin signo, C es el tipo con mayor rango de conversión entera .
  • De lo contrario, un tipo entre T1 y T2 es un tipo entero con signo S , el otro tipo es un tipo entero sin signo U . Aplicar las siguientes reglas:
  • Si el rango de conversión entera de U es mayor o igual que el rango de conversión entera de S , C es U .
  • En caso contrario, si S puede representar todos los valores de U , C es S .
  • En caso contrario, C es el tipo entero sin signo correspondiente a S .

Si un operando es de tipo enumeración y el otro operando es de un tipo de enumeración diferente o un tipo de punto flotante, este comportamiento está obsoleto.

(since C++20)
(until C++26)

Rango de conversión de enteros

Cada tipo entero tiene un rango de conversión entera definido de la siguiente manera:

  • Ningún otro par de tipos enteros con signo, aparte de char y signed char (si char tiene signo), tiene 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:
  • long long
(desde C++11)
  • long
  • int
  • short
  • signed char
  • El rango de cualquier tipo entero sin signo es igual al rango del tipo entero con signo correspondiente.
  • El rango de cualquier tipo entero estándar es mayor que el rango de cualquier tipo entero extendido con el mismo ancho.
(since C++11)
  • El rango de bool es menor que el rango de todos los tipos enteros estándar.
  • Los rangos de los tipos de caracteres de codificación ( char , char8_t (desde C++20) , char16_t , char32_t , (desde C++11) y wchar_t ) son iguales a los rangos de sus tipos subyacentes , lo que significa:
  • El rango de char es igual al rango de signed char y unsigned char .
  • El rango de char8_t es igual al rango de unsigned char .
(desde C++20)
(desde C++11)
  • El rango de wchar_t es igual al rango de su tipo subyacente definido por la implementación.
  • El rango de cualquier tipo entero con signo extendido relativo a otro tipo entero con signo extendido con el mismo ancho está definido por la implementación, pero aún sujeto a las otras reglas para determinar el rango de conversión entera.
(desde C++11)
  • Para todos los tipos enteros T1 , T2 , y T3 , si T1 tiene mayor rango que T2 y T2 tiene mayor rango que T3 , entonces T1 tiene mayor rango que T3 .

El rango de conversión entera también se utiliza en la definición de integral promotion .

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 como sigue:

  • Los rangos de los tipos de punto flotante estándar disminuyen en orden:
    • long double
    • double
    • float
  • El rango de un tipo de punto flotante T es mayor que el rango de cualquier tipo de punto flotante cuyo conjunto de valores es un subconjunto propio del conjunto de valores de T .
  • Dos tipos de punto flotante extendidos con el mismo conjunto de valores tienen rangos iguales.
  • Un tipo de punto flotante extendido con el mismo conjunto de valores que exactamente un tipo de punto flotante estándar sin calificación cv tiene un rango igual al rango de ese tipo de punto flotante estándar.
  • Un tipo de punto flotante extendido con el mismo conjunto de valores que más de un tipo de punto flotante estándar sin calificación cv tiene un rango igual al rango de double .
(desde C++23)


Subrango de conversión de punto flotante

Los tipos de punto flotante que tienen igual rango de conversión de punto flotante se ordenan mediante el subrango de conversión de punto flotante . El subrango forma un orden total entre tipos con rangos iguales.

Los tipos std::float16_t , std::float32_t , std::float64_t , y std::float128_t ( tipos de punto flotante de ancho fijo ) tienen un mayor subrango de conversión que cualquier tipo de punto flotante estándar con igual rango de conversión. En caso contrario, el orden del subrango de conversión está definido por la implementación.

(desde C++23)

Uso

El rango de conversión de punto flotante y el subrango también se utilizan para

(desde C++23)

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 1642 C++98 las conversiones aritméticas usuales podían involucrar lvalues aplica primero las conversiones lvalue-to-rvalue
CWG 2528 C++20 la comparación de tres vías entre unsigned char
y unsigned int estaba mal formada debido
a la promoción integral intermedia [1]
determina el tipo común basándose
en los tipos promocionados, sin
promover realmente los operandos [2]
CWG 2892 C++98 cuando ambos operandos son del mismo
tipo de punto flotante, el significado de "no
se necesita más conversión" no estaba claro
cambiado a "no se realizará
más conversión"
  1. Antes de la resolución, unsigned char se promueve a int al inicio de la etapa 5, luego se convierte a unsigned int . Sin embargo, esta última conversión es restrictiva, lo que hace que la comparación de tres vías sea incorrecta.
  2. Después de la resolución, el tipo común sigue siendo unsigned int . La diferencia es que unsigned char se convierte directamente a unsigned int sin la promoción integral intermedia. La conversión no es restrictiva y por lo tanto la comparación de tres vías es correcta.