207 votes

Type de retour de '?:' (Opérateur conditionnel ternaire)

Pourquoi le premier renvoie une référence?

 int x = 1;
int y = 2;
(x > y ? x : y) = 100;
 

Alors que le second ne le fait pas?

 int x = 1;
long y = 2;
(x > y ? x : y) = 100;
 

En fait, la seconde n'a pas compilé du tout - "pas de gauche gauche de l'affectation".

173voto

Charles Bailey Points 244082

Les Expressions n'ont pas de type de retour, ils ont un type et - comme il est connu dans le dernier C++ standard - la valeur de la catégorie.

Une expression conditionnelle peut être une lvalue ou une rvalue. Cette valeur est sa valeur de la catégorie. (C'est une sorte de simplification, en C++11, nous avons lvalues, xvalues et prvalues.)

En large et en termes simples, une lvalue se réfère à un objet en mémoire et une rvalue est juste une valeur qui ne peuvent pas nécessairement être attaché à un objet en mémoire.

Une expression d'affectation affecte une valeur à un objet donc, la chose étant affecté doit être une lvalue.

Pour une expression conditionnelle (?:) à être une lvalue (encore une fois, en large et en termes simples), la deuxième et la troisième les opérandes doivent être lvalues du même type. C'est parce que le type et la valeur de la catégorie d'une expression conditionnelle est déterminé au moment de la compilation et doivent être appropriées si oui ou non la condition est vraie. Si l'un des opérandes doit être converti en un autre type pour correspondre à l'autre alors l'expression conditionnelle ne peut pas être une lvalue que le résultat de cette conversion ne serait pas une lvalue.

ISO/IEC 14882:2011 références:

3.10 [de base.lval] Lvalues et rvalues (sur la valeur des catégories)

5.15 [expr.cond] opérateur Conditionnel (règles de ce type et la valeur de la catégorie d'une expression conditionnelle a)

5.17 [expr.cul] la Cession et composé des opérateurs d'affectation (exigence de la présence de l.h.s. de l'affectation doit être modifiable lvalue)

57voto

Xeo Points 69818

Le type de l'expression ternaire ?: est le type commun de ses deuxième et troisième arguments. Si les deux types sont identiques, vous obtenez une référence. Si elles sont convertibles l'une à l'autre, l'une est choisie et l'autre est convertie (promue dans ce cas). Comme vous ne pouvez pas renvoyer une référence lvalue à une variable temporaire (la variable convertie / promue), son type est un type de valeur.

19voto

Filip Roséen - refp Points 24995

Il ne peut pas retourner une lvalue puisqu'il aura implicitement à promouvoir le type d' x en fonction du type d' y (depuis les deux côtés de l' : ne sont pas du même type), et avec qui il a de créer un temporaire.


Quelle est la norme de dire? (n1905)

Expressions 5.17 Affectation et composé des opérateurs d'affectation

5.17/3

Si le deuxième et le troisième opérande de différents types, et soit a (éventuellement cv qualifiés) type de classe, une tentative est faite pour convertir chacune de ces opérandes type de l'autre. Le processus permettant de déterminer si un opérande de l'expression E1 de type T1 peut être converti pour correspondre à un opérande expression E2 de type T2 est définie comme suit:

- Si E2 est une lvalue: E1 peut être converti pour correspondre E2 si E1 peut être implicitement converti (alinéa 4) du type "référence à T2", soumis à la contrainte que dans la conversion de la référence doit se lier directement (8.5.3) de E1.

- Si E2 est une rvalue, ou si la conversion ci-dessus ne peut pas être fait:

- si E1 et E2 ont le type de classe, et la classe sous-jacente types sont les mêmes ou l'un est une classe de base de l'autre: E1 peut être converti pour correspondre E2 si la classe de T2 est le même type, ou d'une classe de base, la classe de T1, et le cv-qualification de T2 est le même cv-diplôme, ou un plus grand cv-qualification que, le cv-qualification de T1. Si la conversion est demandée, E1 est une rvalue de type T2 qui fait toujours référence à la source originale de la classe de l'objet (ou le sous-objet de celui-ci). [Note: c'est, aucune copie n'est effectuée. - fin de la remarque] par copier-initialisation temporaire de type T2 à partir de E1 et de l'aide que temporaire, car la conversion d'un opérande.

Dans le cas contraire (c'est à dire, si E1 ou E2 a un non type de classe, ou si elles ont toutes les deux types de classe, mais les classes sous-jacentes ne sont pas de la même ou de l'un d'une classe de base de l'autre): E1 peut être converti pour correspondre E2 si E1 peut être implicitement converti dans le type de l'expression E2 si E2 ont été converties en une rvalue (ou le type il a, si E2 est une rvalue).

À l'aide de ce processus, Il est déterminé si le deuxième opérande peut être converti pour correspondre à la troisième opérande, et si le troisième opérande peut être converti pour correspondre à la deuxième opérande. Si les deux peuvent être convertis, ou l'on peut être converti, mais la conversion est ambigu, le programme est mal formé. Si l'un ne peut être converti, les opérandes ne sont pas modifiées et plus de la vérification est effectuée comme décrit ci-dessous. Si exactement une conversion est possible, que la conversion est appliqué à la choisi opérande et le converti opérande est utilisé à la place de l'original opérande pour le reste de cette section.


5.17/4

Si la deuxième et la troisième les opérandes sont des lvalues et ont le même type, le résultat est de ce type et est une lvalue et c'est un peu-champ si la deuxième ou la troisième opérande est un peu de champ, ou si les deux sont des bits de champs.


5.17/5

Sinon, le résultat est une rvalue. Si les deuxième et troisième opérandes n'ont pas le même type, et soit a (éventuellement cv qualifiés) type de classe, de résolution de surcharge est utilisé pour déterminer le taux de conversion (le cas échéant) pour être appliqué sur les opérandes (13.3.1.2, 13.6). Si la résolution de surcharge échoue, le programme est mal formé. Sinon, les conversions ainsi déterminés sont appliquées, et les convertis opérandes sont utilisés à la place de l'original opérandes pour le reste de cette section.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X