Conversiones implícitas
Las conversiones implícitas se realizan cada vez que una expresión de algún tipo T1
se utiliza en un contexto que no acepta ese tipo, pero acepta algún otro tipo T2
; en particular:
- cuando la expresión se utiliza como el argumento al llamar a una función que se declara con
T2
como parámetro; - cuando la expresión se utiliza como un operando con un operador que espera
T2
; - cuando se inicializa un nuevo objeto de tipo
T2
, incluyendo la instrucciónreturn
en una función que devuelveT2
; - cuando se usa la expresión en una instrucción switch (
T2
es de tipo entero); - cuando se usa la expresión en una instrucción if o un bucle (
T2
es de tipo bool).
El programa está bien formado (se compila) sólo si existe una secuencia de conversión implícita inequívoca de T1
a T2
.
Si hay varias sobrecargas de la función o el operador que se llama, después que la secuencia de conversión implícita se construye a partir de T1
para cada T2
disponible, las reglas de resolución de sobrecarga deciden cuál sobrecarga se compila.
Nota: En expresiones aritméticas, el tipo de destino de las conversiones implícitas en los operandos dados a los operadores binarios se determina por un conjunto de reglas separado: conversiones aritméticas habituales.
Contenido |
[editar] Orden de las conversiones
La secuencia de la conversión implícita consiste en lo siguiente, en este orden:
Al considerar el argumento de un constructor o de una función de conversión definida por el usuario, se permite solamente una secuencia de conversión estándar (de lo contrario, las conversiones definidas por el usuario podrían estar efectivamente encadenadas). Al convertir de un tipo no-clase a otro tipo no-clase, se permite solamente una secuencia de conversión estándar.
Una secuencia de conversión estándar consiste en lo siguiente, en este orden:
- conversión l-valor a r-valor,
- conversión de array a puntero, y
- conversión puntero a función;
3) cero o una conversión puntero a función;
|
(desde C++17) |
Una conversión definida por el usuario consiste de cero o un constructor de conversión no explícito, de un solo argumento, o de una llamada a función de conversión no explícita.
Se dice que una expresión e es implícitamente convertible a T2
si y sólo si la declaración T2
puede ser inicializada por copia de e
, es decir, la declaración T2 t = e; está bien formada (puede compilarse) para algún objeto temporal arbitrario t
. Observa que esto es diferente de la inicialización directa (T2 t(e)), donde se considerarían adicionalmente los constructores explícitos y las funciones de conversión.
[editar] Conversiones contextuales
En los siguientes contextos, se espera el tipo bool t la conversión implícita se realiza si la declaración bool t(e); está bien formada (es decir, una función de conversión explícita tal como
|
(desde C++11) |
En los siguientes contextos, se espera un tipo T
específico del contexto, y la expresión e de tipo clase E
solamente se permite si
|
(hasta C++14) |
|
(desde C++14) |
Tal expresión e se dice que es contextualmente implícitamente convertida al tipo especificado T
. Observa que las funciones de conversión explícitas no se consideran, aun cuando se consideran en las conversiones contextuales a bool. (desde C++11)
- el argumento de la expresión delete (
T
es cualquier objeto de tipo puntero); - expresión constante entera, donde se usa una clase literal (
T
es cualquier tipo entero o tipo enumeración sin ámbito, la función de conversión definida por el usuario seleccionada debe ser constexpr); - la expresión de control de la instrucción
switch
(T
es cualquier tipo entero o tipo enumeración).
#include <cassert> template<typename T> class inic_cero { T val; public: inic_cero() : val(static_cast<T>(0)) { } inic_cero(T val) : val(val) { } operator T&() { return val; } operator T() const { return val; } }; int main() { inic_cero<int> i; assert(i == 0); i = 7; assert(i == 7); switch(i) { } // ERROR hasta C++14 (más de una función de conversión) // de acuerdo desde C++14 (ambas funciones convierten al mismo tipo int) switch(i + 0) { } // siempre de acuerdo (conversión implícita) }
[editar] Transformaciones de valor
Las transformaciones de valor son conversiones que cambian la categoría de valor de una expresión. Toman lugar cada vez que una expresión aparece como un operando de un operador que espera una expresión de una categoría de valor diferente:
- Siempre que un gl-valor aparece como un operando de un operador que requiere un pr-valor para ese operando, se aplican las conversiones estándar de l-valor a r-valor, array a puntero o función a puntero para convertir la expresión en un pr-valor.
|
(desde C++17) |
[editar] Conversión de l-valor a r-valor
Un l-valor (hasta C++11)Un gl-valor (desde C++11) de cualquier tipo T
no función, no tipo array, se puede convertir implícitamente en un r-valor (hasta C++11)un pr-valor (desde C++11):
- Si
T
no es un tipo clase, el tipo de r-valor (hasta C++11)pr-valor (desde C++11) es la versión no calificada-cv deT
. - De lo contrario, el tipo de r-valor (hasta C++11)pr-valor (desde C++11) es
T
.
Si un programa requiere una conversión de l-valor a r-valor de un tipo incompleto, el programa está mal formado.
Cuando se produce una conversión de l-valor a r-valor dentro del operando de |
(hasta C++11) |
Cuando se aplica una conversión de l-valor a r-valor a una expresión E, no se accede al valor contenido en el objeto referenciado si:
|
(desde C++11) |
El resultado de la conversión es el valor contenido en el objeto indicado por el l-valor. |
(hasta C++11) | ||||||
El resultado de la conversión se determina de acuerdo con las siguientes reglas:
|
(desde C++11) |
Esta conversión modela el acto de leer un valor desde una ubicación de memoria en un registro de CPU.
[editar] Conversión de array a puntero
Un l-valor o r-valor de tipo "array de N
T
" o "array de límite desconocido de T
" puede convertirse implícitamente a un pr-valor de tipo "puntero a T
". Si el array es un pr-valor, ocurre la materialización temporal. (desde C++17) El puntero resultante se refiere al primer elemento del array (véase Decadencia de array a puntero para más detalles).
[editar] Conversión de función a puntero
Un l-valor de un tipo función puede convertirse implícitamente a un pr-valor de puntero a esa función. Esto no se aplica a funciones miembro no estáticas porque los l-valores que se refieren a las funciones miembro no estáticas no existen.
Materialización temporalUn pr-valor de cualquier tipo completo Si struct S { int m; }; int i = S().m; // acceso a miembro espera un gl-valor a partir de C++17; // S() pr-valor se convierte a x-valor La materialización temporal ocurre en las siguientes situaciones:
Observa que la materialización temporal no ocurre cuando se inicializa un objeto desde un pr-valor del mismo tipo (por inicialización directa o inicialización de copia): tal objeto se inicializa directamente desde el inicializador. Esto garantiza la "elisión de copia obligatoria". |
(desde C++17) |
[editar] Promociones de enteros
Los pr-valores de tipos enteros pequeños (como char) y tipos enumeración sin ámbito pueden convertirse a pr-valores de tipos enteros más grandes (como int). En particular, los operadores aritméticos no aceptan tipos más pequeños que int como argumentos, y las promociones de enteros se aplican automáticamente después de una conversión de l-valor a r-valor, si se aplica. Esta conversión siempre conserva el valor.
Las siguientes conversiones implícitas se clasifican como promociones de enteros.
Ten en cuenta que, para un tipo de origen determinado, el tipo de destino de la promoción de entero es única y todas las demás conversiones no son promociones. Por ejemplo, la resolución de sobrecarga elige char -> int (promoción) en lugar de char -> short (conversión).
[editar] Promoción a partir de tipos enteros
Un pr-valor de tipo bool se puede convertir a un pr-valor de tipo int, donde false se convierte en 0 y true se convierte en 1.
Para un pr-valor val de un tipo entero T
excepto bool:
- val se puede convertir a un pr-valor de tipo int si int puede representar todos los valores del campo de bits;
- de lo contrario, val se puede convertir a unsigned int si unsigned int puede representar todos los valores del campo de bits;
- de lo contrario, val se puede convertir de acuerdo con las reglas especificadas en el punto (3).
- si
T
es char8_t, (desde C++20)char16_t, char32_t o (desde C++11)wchar_t, val se puede convertir de acuerdo con las reglas especificadas en el elemento (3); - de lo contrario, si el rango de conversión de enteros de
T
es inferior al rango de int:
- val se puede convertir en un pr-valor de tipo int si int puede representar todos los valores de
T
; - de lo contrario, val se puede convertir en un pr-valor de tipo unsigned int.
- val se puede convertir en un pr-valor de tipo int si int puede representar todos los valores de
T
es uno de los tipos de caracteres dados), val se puede convertir en un pr-valor del primero de los siguientes tipos que pueden representar todos los valores de su tipo subyacente:
- int
- unsigned int
- long
- unsigned long
|
(desde C++11) |
[editar] Promoción a partir de tipos enumeración
Un pr-valor de un tipo enumeración sin ámbito cuyo tipo subyacente no es fijo se puede convertir en un pr-valor del primer tipo de la siguiente lista capaz de contener todo su rango de valores:
- int
- unsigned int
- long
- unsigned long
|
(desde C++11) |
Un tipo enumeración sin ámbito cuyo tipo subyacente está fijo puede convertirse a su tipo subyacente. Además, si el tipo subyacente también está sujeto a una promoción de entero, al tipo promocionado del tipo subyacente. La conversión al tipo subyacente no promocionado es mejor para propósitos de resolución de sobrecarga. |
(desde C++11) |
[editar] Promociones de punto flotante
Un pr-valor de tipo float puede convertirse a un pr-valor de tipo double. El valor no cambia.
Esta conversión se llama promoción de punto flotante.
[editar] Conversiones numéricas
A diferencia de las promociones, las conversiones numéricas pueden cambiar los valores, con la posible pérdida de precisión.
[editar] Conversiones de enteros
Un pr-valor de un tipo entero o de un tipo enumeración sin ámbito se puede convertir a cualquier otro tipo entero. Si la conversión se encuentra dentro de las promociones de entero, es una promoción y no una conversión.
- Si el tipo de destino es sin signo, el valor resultante es el valor sin signo más pequeño igual al valor fuente módulo 2n
donde n es el número de bits para representar el tipo de destino.
- Es decir, dependiendo si el tipo de destino es más ancho o más estrecho, se extiende el signo a los enteros con signo[1] o son truncados, y se extiende el cero a los enteros sin signo o son truncados, respectivamente.
- Si el tipo de destino tiene signo, el valor no caambia si el entero fuente puede representarse en el tipo de destino. De otra manera el resultado está definido por la implementación (hasta C++20) el valor único del tipo de destino de igual al módulo del valor fuente 2n
donde n es el número de bits usado para representar el tipo de destino. (desde C++20). (Ten en cuenta que esto es diferente del desborde aritmético de enteros con signo, que no está definido). - Si el tipo fuente es bool, el valor false se convierte a cero y el valor true se convierte al valor uno del tipo de destino (ten en cuenta que si el tipo de destino es int, esto es una promoción de entero, no una conversión de entero).
- Si el tipo de destino es bool, esto es una conversión booleana (véase abajo).
- ↑ Esto solamente se aplica si la aritmética es de complemento a dos, que se requiere solamente por los tipos enteros de anchura exacta. Ten en cuenta, sin embargo, que en este momento todas las plataformas con un compilador de C++ utilizan aritmética de complemento a dos
[editar] Conversiones de punto flotante
Un pr-valor de un tipo de punto flotante se puede convertir en un pr-valor de cualquier otro tipo de punto flotante. |
(hasta C++23) |
Un pr-valor de un tipo de punto flotante se puede convertir en un pr-valor de cualquier otro tipo de punto flotante con un rango de conversión de punto flotante mayor o igual. Un pr-valor de un tipo de punto flotante estándar se puede convertir a un pr-valor de cualquier otro tipo de punto flotante estándar.
|
(desde C++23) |
Si la conversión se encuentra dentro de las promociones de punto flotante, es una promoción y no una conversión.
- Si el valor fuente se puede representar exactamente en el tipo de destino, no cambia.
- Si el valor fuente está entre dos valores representables del tipo de destino, el resultado es uno de esos dos valores (está definido por la implementación cuál de los dos, aunque si se admite la aritmética de la IEEE, el redondeo por defecto es al más cercano).
- De lo contrario, el comportamiento no está definido.
[editar] Conversiones entre tipos de punto flotante y enteros
Un pr-valor de tipo de punto flotante se puede convertir en un pr-valor de cualquier tipo entero. La parte fraccionaria se trunca, es decir, la parte fraccionaria se descarta.
- Si el valor no puede encajar en el tipo de destino, el comportamiento no está definido (aun cuando el tipo de destino es sin signo, la aritmética de módulo no se aplica).
- Si el tipo de destino es bool, esto es una conversión booleana (véase abajo).
Un pr-valor de tipo entero o de tipo enumeración sin ámbito se puede convertir en un pr-valor de cualquier tipo de punto flotante.
- Si el valor no puede ser representado correctamente, está definido por la implementación si el valor cercano más alto o el valor cercano más bajo será seleccionado, aunque si se admite la aritmética de la IEEE, el redondeo por defecto es al más cercano.
- Si el valor no puede encajar en el tipo de destino, el comportamiento no está definido.
- Si el tipo fuente es bool, el valor false se convierte a cero, y el valor true se convierte a uno.
[editar] Conversiones de punteros
Una constante de puntero nulo (véase NULL) puede convertirse a cualquier tipo de puntero, y el resultado es el valor del puntero nulo de ese tipo. Tal conversión (conocida como la conversión de puntero nulo) se permite para convertir un tipo calificado-cv como una sola conversión, es decir, no se considera una combinación de conversiones numéricas y calificadas.
Un puntero de pr-valor a cualquier (opcionalmente calificado-cv) tipo objeto T
puede convertirse a un puntero de pr-valor a (idénticamente calificado-cv) void. El puntero resultante representa la misma ubicación en memoria que el valor del puntero original.
- Si el puntero original es un valor de puntero nulo, el resultado es el valor del puntero nulo del tipo de destino.
Un pr-valor ptr de tipo “puntero a (posiblemente calificado-cv) Derived
” se puede convertir a un pr-valor de tipo “puntero a (posiblemente calificado-cv) Base
”, donde Base
es una clase base de Derived
, y Derived
es un tipo clase completo. Si Base
es inaccesible o ambiguo, el programa está mal formado.
- Si ptr es un valor de puntero nulo, el resultado también es un valor de puntero nulo.
- De lo contrario, si
Base
es una clase base virtual deDerived
y ptr no apunta a un objeto cuyo tipo sea similar aDerived
y que esté dentro de su tiempo de vida o dentro de su período de construcción o destrucción, el comportamiento no está definido. - De lo contrario, el resultado es un puntero al subobjeto de la clase base del objeto de la clase derivada.
[editar] Conversiones de puntero a miembro
- Una constante de puntero nulo puede convertirse a cualquier tipo de puntero a miembro, y el resultado es el valor de puntero a miembro nulo de tal tipo. Dicha conversión (conocida como la conversión de puntero a miembro nulo) se permite para convertir un tipo calificado-cv como una sola conversión, es decir, no se considera una combinación de conversiones numéricas y calificadas.
Un pr-valor de tipo “puntero a miembro de Base
de tipo (posiblemente calificado-cv) T
” se puede convertir en un pr-valor de tipo “puntero a miembro de Derived
de tipo (idénticamente calificado-cv) T
”, donde Base
es una clase base de Derived
y Derived
es un tipo clase completo. Si Base
es inaccesible, ambiguo o base virtual de Derived
o es una base de alguna base virtual intermedia de Derived
, el programa está mal formado.
- Si
Derived
no contiene el miembro original y no es una clase base de la clase que contiene el miembro original, el comportamiento no está definido. - De lo contrario, el puntero resultante se puede desreferenciar con un objeto
Derived
y accederá al miembro dentro del subobjeto baseBase
de ese objetoDerived
.
[editar] Conversiones booleanas
Un pr-valor de tipos entero, punto flotante, enumeración sin ámbito, puntero, y puntero a miembro puede convertirse a un pr-valor de tipo bool.
El valor cero (para tipos enteros, de punto flotante y enumeraciones sin ámbito), y los valores del puntero nulo y el puntero a miembro nulo se convierten en false. Todos los otros valores se convierten en true.
En el contexto de una inicialización directa, un objeto bool puede inicializarse desde un pr-valor de tipo std::nullptr_t, incluyendo nullptr. El valor resultante es false. Sin embargo, esto no se considera una conversión implícita. |
(desde C++11) |
[editar] Conversiones de calificación
En términos generales:
- Un pr-valor de tipo puntero al tipo calificado-cv
T
puede convertirse a un puntero de pr-valor a un mismo tipo más calificado-cvT
. En otras palabras, se puede añadir, constantitud (const) y volatilidad (volatile). - Un pr-valor de tipo puntero a miembro de un tipo calificado-cv
T
en la claseX
puede convertirse a un puntero de pr-valor a miembro de un tipo más calificado-cvT
en la claseX
.
La definición formal de “conversión de calificaciones se da en a continuación.
[editar] Tipos similares
De manera informal, dos tipos son similares si, ignorando la calificación-cv de nivel superior:
- son del mismo tipo; o
- ambos son punteros y los tipos a los que apuntan son similares; o
- ambos son punteros a miembro de la misma clase y los tipos de los miembros a los que apuntan son similares; o
- ambos son arrays y los tipos de elementos del array son similares.
Por ejemplo:
- const int* const * y int** son similares;
- int (*)(int*) y int (*)(const int*) no son similares;
- const int (*)(int*) y int (*)(int*) no son similares;
- int (*)(int* const) y int (*)(int*) son similares (son del mismo tipo);
- std::pair<int, int> y std::pair<const int, int> no son similares.
Formalmente, la similitud de tipos se define en términos de descomposición de calificación.
Una descomposición de calificación de un tipo T
es una secuencia de componentes cv_i
y P_i
tal que T
es “cv_0 P_0 cv_1 P_1 ... cv_n−1 P_n−1 cv_n U
” para n no negativo, donde
- cada
cv_i
es un conjunto de const y volatile, y - cada
P_i
es
- “puntero a”,
- “puntero a miembro de la clase
C_i
de tipo”, - “array de N_i”, o
- “array de límite desconocido de”.
Si P_i
designa un array, los calificadores-cv cv_i+1
del tipo de elemento también se toman como los calificadores-cv cv_i
del array.
// T es un puntero a puntero a const int”, tiene 3 descomposiciones de calificación: // n = 0 -> cv_0 está vacío, U es “puntero a puntero a const int” // n = 1 -> cv_0 está vacío, P_0 es “puntero a”, // cv_1 está vacío, U es “puntero a const int” // n = 2 -> cv_0 está vacío, P_0 es “puntero a”, // cv_1 está vacío, P_1 es “puntero a”, // cv_2 es “const", U es “int” using T = const int**; // Sustituir cualquiera de los siguientes tipos en U da una de las descomposiciones: // U = U0 -> la descomposición con n = 0: U0 // U = U1 -> la descomposición con n = 1: puntero a [U1] // U = U2 -> la descomposición con n = 2: puntero a [puntero a [const U2]] using U2 = int; using U1 = const U2*; using U0 = U1*;
Dos tipos T1
y T2
son similares si existe una descomposición de calificación para cada uno de ellos, donde se satisfacen todas las siguientes condiciones para las dos descomposiciones de calificación:
- Tienen la misma n.
- Los tipos denotados por
U
son los mismos. - Los componentes correspondientes de
P_i
son los mismos o uno es array de N_i” y el otro es array de límite desconocido de” para toda i.
// la descomposición de calificación con n = 2: // puntero a [volatile puntero a [const int]] using T1 = const int* volatile *; // la descomposición de calificación con n = 2: // const puntero a [puntero a [int]] using T2 = int** const; // Para las dos descomposiciones de calificación anteriores, // aunque cv_0, cv_1 y cv_2 son todos diferentes, // tienen el mismo n, U, P_0 y P_1, // por lo tanto, los tipos T1 y T2 son similares.
[editar] Combinación de calificaciones-cv
En la descripción que aparece a continuación, la descomposición de calificación más larga del tipo Tn
se denota como Dn
, y sus componentes se denotan como cvn_i
y Pn_i
.
Una expresión pr-valor del tipo
El tipo de calificación combinada de dos tipos
|
(hasta C++20) |
El tipo de calificación combinada de dos tipos
Un pr-valor de tipo |
(desde C++20) |
// descomposición de calificación más larga T1 (n = 2): // puntero a [puntero a [char]] using T1 = char**; // descomposición de calificación más larga T2 (n = 2): // puntero a [puntero a [const char]] using T2 = const char**; // Determining the cv3_i and T_i components of D3 (n = 2): // cv3_1 = vacío (unión de cv1_1 vacío y cv2_1 vacío) // cv3_2 = “const” (unión de cv1_2 vacío y “const” cv2_2 vacío) // P3_0 = “puntero a” (no array de límite desconocido, usar P1_0) // P3_1 = “puntero a” (no array de límite desconocido, usar P1_1) // Todos los componentes excepto cv_2 son iguales, cv3_2 es diferente de cv1_2, // por lo tanto, agregar “const” a cv3_k para cada k en [1, 2): cv3_1 se convierte en “const”. // T3 es “puntero a puntero const a const char”, es decir, const char* const *. using T3 = /* el tipo de calificación combinada de T1 y T2 */; int main() { const char c = 'c'; char* pc; T1 ppc = &pc; T2 pcc = ppc; // ERROR: T3 no es el mismo que T2 no calificado-cv, // no hay conversión explícita. *pcc = &c; *pc = 'C'; // Si se permite la asignación errónea anterior, // el objeto constante “c” puede modificarse. }
Ten en cuenta que en el lenguaje de programación C, const/volatile se puede agregar solo al primer nivel:
char** p = 0; char * const* p1 = p; // OK en C y C++ const char* const * p2 = p; // error en C, OK en C++
Conversiones de puntero a función
void (*p)(); void (**pp)() noexcept = &p; // ERROR: no se puede convertir a puntero a función noexcept struct S { typedef void (*p)(); operator p(); }; void (*q)() noexcept = S(); // ERROR: no se puede convertir a puntero a función noexcept |
(desde C++17) |
[editar] El problema del booleano seguro
Hasta la introducción de funciones de conversión explícitas en C++11, diseñar una clase que debía ser utilizable en contextos booleanos (p. ej., if (obj) { ... }) presentaba un problema: dada una función de conversión definida por el usuario, tal como T::operator bool() const;, la secuencia de conversión implícita permitía una secuencia de conversión estándar de esa llamada de función, lo que significaba que el bool resultante podía convertirse a int, permitiendo código como obj << 1; o int i = obj;.
Una solución inicial para esto se puede ver en std::basic_ios, que define operator void*(), de modo que código como if (std::cin) {...} se compila porque void* se puede convertir a bool, pero int n = std::cout; no se compila porque void* no se puede convertir a int. Esto todavía permite que código sin sentido como delete std::cout; se compile.
Muchas bibliotecas de terceros que predecieron a C++11 fueron diseñadas con una solución más elaborada, conocida como el modismo del booleano seguro. std::basic_ios también permitía este modismo a través de Asunto LWG 468, y se reemplazó operator void* (véase la sección notas).
Desde C++11, también se puede usar la conversión explícita de bool para resolver el problema del booleano seguro.
[editar] 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 170 | C++98 | El comportamiento de las conversiones de puntero a miembro no estaba claro si la clase derivada no tiene el miembro original. |
Se aclaró. |
CWG 172 | C++98 | El tipo enumeración se promovía en función de su tipo subyacente. | En su lugar, en función de su rango de valores. |
N4261 | C++98 | La conversión de double* const (*p)[3] a double const * const (*p)[3] no era válida. |
Se hizo válida. |
CWG 519 | C++98 | no se garantizaba que los valores de puntero nulos se conservaran al convertirlos a otro tipo puntero. |
Siempre se conservan. |
CWG 616 | C++98 | El comportamiento de la conversión de l-valor a r-valor de cualquier objeto no inicializado y objetos puntero de valores no válidos siempre estaba indefinido. |
Se permite un unsigned char indeterminado; el uso de punteros no válidos está definido por la implementación. |
CWG 685 | C++98 | El tipo subyacente de un tipo enumeración no se priorizaba en la promoción de entero si era fijo. |
Se prioriza. |
CWG 707 | C++98 | La conversión de entero a punto flotante tenía un comportamiento definido en todos los casos. |
El comportamiento no está definido si el valor que se está convirtiendo está fuera del rango de destino. |
CWG 1423 | C++11 | std::nullptr_t era convertible a bool tanto en la inicialización directa como en la de copia. |
Solo en la inicialización directa. |
CWG 1773 | C++11 | Una expresión de nombre que aparece en una expresión potencialmente evaluada de modo que el objeto nombrado no sea en uso-ODR podría aún evaluarse durante una conversión de l-valor a r-valor. |
No se evalúa. |
CWG 1781 | C++11 | La conversión de std::nullptr_t a bool se consideraba una conversión implícita aunque solo sea válida para la inicialización directa. |
Ya no se considera una conversión implícita. |
CWG 1787 | C++98 | El comportamiento de leer desde un unsigned char indeterminado almacenado en caché en un registro no estaba definido. |
Se hizo bien definido. |
CWG 1981 | C++11 | Las conversiones contextuales se consideraban funciones de conversión explícitas. | No se consideran. |
CWG 2140 | C++11 | No estaba claro si las conversiones de l-valor a r-valor de expresiones l-valores de std::nullptr_t obtenían estas expresiones l-valores de la memoria. |
No se obtienen de memoria. |
CWG 2310 | C++98 | para las conversiones de puntero derivado a base y las conversiones de puntero a miembro de base a derivado, el tipo de clase derivada podría estar incompleto. |
Debe ser completo. |
CWG 2484 | C++20 | char8_t y char16_t tenían diferentes estrategias de promoción de enteros, pero podían encajar en ambas. |
char8_t debe promocionarse de la misma forma que char16_t. |
CWG 2485 | C++98 | Las promociones de enteros que involucran campos de bits no se especificaban bien. | Se mejoró la especificación. |
CWG 2813 | C++23 | La materialización temporal ocurriría cuando se invoca una función miembro de objeto explícita de una clase pr-valor. |
No ocurre en este caso. |
CWG 2861 | C++98 | Un puntero a un objeto de tipo inaccesible podría ser convertido en un puntero a un subobjeto de clase base. |
El comportamiento no está definido en este caso. |
CWG 2879 | C++17 | Se aplicó la conversión de materialización temporal sobre una expresión pr-valor como un operando de un operador que espera una expresión gl-valor. |
No se aplica en algunos casos. |
[editar] Véase también
-
const_cast
-
static_cast
-
dynamic_cast
-
reinterpret_cast
- explicit cast
- Conversión definida por el usuario
Documentación de C para Conversiones implícitas
|