Pointeur problème de conversion avec l'opérateur ternaires
Question
Je sais que l'opérateur ternaire a des restrictions surprenantes, mais j'étais un peu déconcerté que cela ne peut pas compiler pour moi:
void foo(bool b)
{
int* ptr = ((b) ? NULL : NULL);
}
De toute évidence qui est le minimum nécessaire pour montrer le problème. L'erreur est:
[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'
Compiler est le moins que 100% -conforming Embarcadero C ++ Builder 2010, donc un bug du compilateur est loin d'être impossible ...
NOTE: parens modifié pour éviter toute confusion au sujet de mon intention
. NOTE2: Je me suis un peu confus sur la façon dont je suis arrivée à cette construction, en premier lieu, donc voici mon excuse: je recevais des erreurs de compilation sur une ligne comme a = b? c : d
, où b, c et d étaient toutes les expressions complexes. Pour le réduire, je l'ai remplacé c
et d
avec NULL
s afin de vérifier si b
était le coupable. À ce stade, tout est allé en enfer dans une charrette à bras.
La solution
NULL
est une macro qui se développe pour 0
(ou une expression constante intégrale avec une valeur de 0
, par exemple, (1 - 1)
). Ce n'est pas autrement « spécial ».
Toute expression constante intégrale avec une valeur de zéro peut être utilisée comme une constante de pointeur null qui est la raison pour laquelle int* ptr = 0;
est autorisée. Cependant, ici, l'expression est b ? 0 : 0
; ce ne sont pas une expression constante intégrale (b
est pas constante); son type est int
, ce qui est implicitement convertible en int*
La solution serait de préciser explicitement que vous voulez un type de pointeur:
int* const null_int_ptr = 0;
int* ptr = b ? null_int_ptr : null_int_ptr;
L'exemple est un peu artificiel, si: généralement quand on utilise l'opérateur conditionnel, au moins l'un des arguments est en fait un type de pointeur (par exemple b ? ptr : 0
); lorsque l'un des opérandes est un type de pointeur, le 0
est converti implicitement à ce même type de pointeur et donc le type de l'ensemble de l'expression conditionnelle est le type de pointeur, pas int
.
Le seul cas où vous pouvez avoir ce « problème » est là une constante de pointeur NULL est utilisé à la fois comme deuxième et troisième opérandes de l'opérateur conditionnel, ce qui est plutôt bizarre.
Autres conseils
Votre problème est que sur votre système NULL
est défini comme 0
qui est supposé être un entier dans le contexte de l'opérateur ternaire. Si vous static_cast
un des opérandes à int*
il devrait automatiquement promouvoir l'autre.
Mais pourquoi utiliser une telle construction en premier lieu?
NULL
peut être définie comme ayant le type int
ou même long
, de sorte que l'opérateur ternaire a le même type. Il n'y a pas de conversion implicite du type de pointeur, donc compilateur génère une erreur.
Le gotcha est ici qu'il y a une conversion implicite de l'expression constante entière évaluation à zéro (la constante de pointeur null infâme).
Solution possible est explicite ici:
int* ptr = b ? (int*) NULL : NULL;