ternario operador ejemplo c++ conditional-operator null-pointer c++builder-2010 constant-expression

c++ - ejemplo - operador ternario en c



Problema de conversión de puntero con operador ternario (3)

Sé que el operador ternario tiene algunas restricciones sorprendentes, pero me sorprendió un poco que esto no se compilara para mí:

void foo(bool b) { int* ptr = ((b) ? NULL : NULL); }

Obviamente ese es el mínimo necesario para mostrar el problema. El error es:

[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert ''int'' to ''int *''

El compilador es el Embarcadero C ++ Builder 2010 que cumple menos del 100%, por lo que un error del compilador está lejos de ser imposible ...

NOTA: Parens modificado para evitar confusiones sobre mi intención.

NOTA 2: Me confundí un poco acerca de cómo había llegado a este constructo en primer lugar, así que aquí está mi excusa: ¿estaba obteniendo algunos errores de compilación en una línea como a = b? c : d a = b? c : d , donde b, c y d eran todas expresiones complejas. Para reducirlo, reemplacé c y d con NULL s para comprobar si b era el culpable. En este punto, todo se fue al infierno en una carretilla de mano.


Su problema es que en su sistema, NULL se define como 0 que se supone que es un int en el contexto del operador ternario. Si static_cast uno de los operandos a int* debería promover automáticamente el otro.

Pero, ¿por qué están utilizando tal construcción en primer lugar?


NULL es una macro que se expande a 0 (o alguna expresión constante constante con un valor de 0 , por ejemplo, (1 - 1) ). No es de otra manera "especial".

Cualquier expresión de constante integral con un valor de cero se puede utilizar como una constante de puntero nula, que es la razón por la que int* ptr = 0; esta permitido. Sin embargo, aquí, la expresión es b ? 0 : 0 b ? 0 : 0 ; esta no es una expresión constante constante ( b no es constante); su tipo es int , que no es convertible implícitamente a int*

La solución sería especificar explícitamente que desea un tipo de puntero:

int* const null_int_ptr = 0; int* ptr = b ? null_int_ptr : null_int_ptr;

Sin embargo, el ejemplo es un poco artificial: generalmente cuando uno usa el operador condicional, al menos uno de los argumentos es en realidad un tipo de puntero (por ejemplo, b ? ptr : 0 ); cuando uno de los operandos es un tipo de puntero, el 0 se convierte implícitamente al mismo tipo de puntero y, por lo tanto, el tipo de la expresión condicional completa es el tipo de puntero, no el int .

El único caso en el que puede tener este "problema" es cuando se utiliza una constante de puntero nulo como el segundo y tercer operandos del operador condicional, que es bastante extraño.


NULL podría definirse como que tiene el tipo int o incluso long , por lo que el operador ternario tiene el mismo tipo. No hay conversión implícita al tipo de puntero, por lo que el compilador genera un error. Lo que tenemos aquí es que hay una conversión implícita de una expresión de entero constante que se evalúa a cero (la constante del puntero nulo infame).

La posible solución aquí es un reparto explícito:

int* ptr = b ? (int*) NULL : NULL;