J'ai trouvé le code intéressant suivant aujourd'hui :
SomeFunction(some_bool_variable ? 12.f, 50.f : 50.f, 12.f)
J'ai créé un petit échantillon pour reproduire le comportement :
class Vector3f
{
public:
Vector3f(float val)
{
std::cout << "vector constructor: " << val << '\n';
}
};
void SetSize(Vector3f v)
{
std::cout << "SetSize single param\n";
}
void SetSize(float w, float h, float d=0)
{
std::cout << "SetSize multi param: " << w << ", " << h << ", " << d << '\n';
}
int main()
{
SetSize(true ? 12.f, 50.f : 50.f, 12.f);
SetSize(false ? 12.f, 50.f : 50.f, 12.f);
}
Le résultat que j'obtiens en exécutant le code ci-dessus est :
clang++ -std=c++14 -O2 -Wall -pedantic -lboost_system -lboost_filesystem -pthread main.cpp && ./a.out
main.cpp:29:20: warning: expression result unused [-Wunused-value]
SetSize(true ? 12.f, 50.f : 50.f, 12.f);
^~~~
main.cpp:30:21: warning: expression result unused [-Wunused-value]
SetSize(false ? 12.f, 50.f : 50.f, 12.f);
^~~~
2 warnings generated.
SetSize multi param: 50, 12, 0
SetSize multi param: 50, 12, 0
Ce que j'attendais en les deux était qu'un seul paramètre était passé à l'adresse suivante SetSize(float)
. Cependant, deux paramètres sont passés, ce qui est extrêmement déroutant (d'autant plus que le ternaire a la priorité sur la virgule ; j'ai donc supposé que la virgule ne délimitait pas les arguments de fonction dans ce cas). Par exemple, si l'on utilise true
le ternaire devrait donner 12.f, 50.f
. Dans cette expression, la valeur située à gauche de la virgule est abandonnée/ignorée, de sorte que le résultat final devrait être le suivant :
SetSize(50.f);
La deuxième partie de la confusion est que si nous utilisons true
o false
dans le ternaire, les 2 mêmes valeurs sont passées à la fonction. Le site true
le cas doit être h=12, w=50
Je pense...
Je vois que le compilateur essaie de m'avertir de quelque chose, mais je n'arrive pas à comprendre ce qui se passe. Quelqu'un peut-il décomposer cette logique et expliquer le résultat étape par étape ?
1 votes
Vous ne pouvez pas fournir de listes d'arguments avec l'opérateur ternaire. Il ne sélectionne que des valeurs.
6 votes
@EJP : Utilisons la section des réponses pour répondre aux questions. Merci.
0 votes
La grammaire du langage pour l'opérateur conditionnel ne permet pas d'utiliser une expression avec virgule pour la dernière partie (afin d'éviter toute ambiguïté).
0 votes
"Le ternaire a la préséance sur la virgule ; " - non, ce n'est pas le cas ! Le C++ ne peut pas être décrit par une simple préséance des opérateurs ... et c'est le cas spécifique où cela s'effondre.
0 votes
@MartinBonner Lorsque l'on compare le ternaire aux virgules utilisées de manière non spécialisée, oui il a la priorité sur la virgule. Ce que signifie une virgule dans différentes situations est une discussion différente.
0 votes
@void.pointer : In
a ? b, c : d;
La virgule a une plus grande priorité que le ternaire. Dansa ? b : d , c;
La virgule a une priorité inférieure à celle du ternaire. La "préséance" ne décrit pas adéquatement ce cas - il faut regarder la grammaire.0 votes
@MartinBonner Bon point, je lisais le code comme "
a
est évalué en premier, et seulement sitrue
nous analysons l'expressionb, c
". De cette façon, l'expression ternaire est évaluée en premier, puis l'opérateur virgule est traité.