Pourquoi utiliser “b < a ? a : b” au lieu de “a < b ? b:” pour mettre en œuvre max modèle?
Les Modèles C++ - Le Guide Complet de la 2e Édition introduit le max modèle:
template<typename T>
T max (T a, T b)
{
//if b < a then yield a else yield b
return b < a ? a : b;
}
Et il explique à l'aide de “b < a ? a : b”
au lieu de “a < b ? b : a”
:
Noter que le max() modèle selon [StepanovNotes]
intentionnellement renvoie “b < a ? a : b” au lieu de “a < b ? b:” à
s'assurer que la fonction se comporte correctement, même si les deux valeurs sont
équivalent, mais n'est pas égal.
Comment comprendre les "even if the two values are equivalent but not equal.
"? “a < b ? b : a”
semble avoir le même résultat pour moi.
- Regarde mal pour moi... les Deux réponses sont "correctes", mais si
a
etb
sont équivalent, puis!(a < b) && !(b < a)
est vrai, alorsa < b
etb < a
sont faux, donc dansb < a ? a : b
,b
est retourné, ce qui n'est pas ce que vous voulez... Vous vouleza < b ? b : a
. - Vous pouvez souvent distinguer entre l'équivalent
a
etb
avecstd::addressof
et. al. - Si vous ne
a = max(a, b);
(à plusieurs reprises), vous pourriez ne pas vouloir remplacera
inutilement. - BTW, ce modèle doit prendre des paramètres par const-références et de les retourner par la const-référence, sinon, vous faites un tas de copies inutiles (et vous allez remplacer
a
avec une copie dea
). - L'canonique de type qui a à la fois de l'équivalence et de l'égalité est la CaseInsensitiveString. Pour ce type, ni un<A ni<un. Mais
std::addressof
n'est pas pertinent. En fait, pour leT max(T a, T b)
nous savons déjàaddressof(a) != addressof(b)
. - ah, je pensais
std::max
, n'a pas remarqué le modèle de valeur - Vous pouvez consulter Stepano v Notes sur la Programmation pour plus de détails j'ai tweeté à propos de cette après la lecture que parce que l'explication n'était pas assez détaillée.
- Hilarant. Combien de programmeurs c++ ne prend-il pour écrire le
max
fonction? Ils devraient peut-être faire deux fonctionsmaxFirstIfEqual
etmaxSecondIfEqual
juste pour rendre les choses encore plus risible.
Vous devez vous connecter pour publier un commentaire.
std::max(a, b)
est en effet spécifié pour revenira
lorsque les deux sont équivalents.Qui est considéré comme une erreur par Stepanov et les autres, car il se décompose de la propriété utile que, compte tenu de
a
etb
, vous pouvez toujours les trier avec{min(a, b), max(a, b)}
; pour que, vous voulezmax(a, b)
de retourb
lorsque les arguments sont équivalentes.{min(a, b), max(b, a)}
?max(a,b)
en retourner une si-et-seulement-simin(a,b)
retourne b, et vice versa, de sorte qu'ils sont à l'inverse les uns des autres et de la (non ordonnée) ensemble{min(a,b), max(a,b)}
est toujours égale à{a,b}
.{min(a, b), max(a, b)}
"min(a,b), max(a,b)}
")std::max
est ce que c'est, si les deux sont équivalents, ils sont triés correctement peu importe à qui on vient en premier et que l'on vient en dernier.a, b
ena, a
ne l'est pas.a
est équivalent àb
? Si ils ne sont pas complètement interchangeables, ils ne devraient pas être égaux. Il me semble que le problème est avec la conception du contenu dea
etb
, pas avecmax
oumin
.min
etmax
à rien, mais la timestamp (la clé de tri) dans ce scénario n'a aucun sens. Les événements (les objets) eux-mêmes ne devraient même pas être comparables si l'égalité ne signifie pas l'interchangeabilité. La seule façon{min(a, b), max(a, b)}
fait aucun sens comme une sorte de mécanisme est si les objets sont interchangeables.Cette réponse explique pourquoi le code est faux à partir d'un C++ standard point-de-vue, mais il est hors de contexte.
Voir @T. C. la réponse de pour une explication contextuelle.
La norme définit
std::max(a, b)
comme suit [alg.min.max] (l'emphase est mienne):Équivalent ici signifie que
!(a < b) && !(b < a)
esttrue
[alg.le tri#7].En particulier, si
a
etb
sont équivalent, les deuxa < b
etb < a
sontfalse
, de sorte que la valeur sur le droit de:
sera renvoyé à l'opérateur conditionnel, donca
doit être sur la droite, donc:...semble être la bonne réponse. C'est la version utilisée par libstdc++ et libc++.
De sorte que l'information dans votre citation semble erroné selon la norme actuelle, mais le contexte dans lequel elle est définie peuvent être différentes.
X
).a<b
etb<a
peut à la fois être faux parce qu'ils sont non ordonnée (un ou deux NaN, donc==
est faux aussi). Qui pourrait être considéré comme une sorte d'équivalence. vaguement liés: x86 estmaxsd a, b
instruction met en œuvrea = max(b,a) = b < a ? a : b
. (Quelle est l'instruction qui donne sans branches FP min et max sur x86?). L'instruction continue la source et l'opérande (le 2ème) sur la non-ordonnée, donc une boucle sur un tableau, vous donnera NaN si il y avait des NaNs. Maismax_seen = max(max_seen, a[i])
ignore les NaNs.Le point qui devra être retourné quand ils sont l'équivalent;
std::max
a retournera
(le premier argument) pour ce cas.Donc
a < b ? b : a
doit être utilisée; d'autre part,b < a ? a : b;
sera de retourb
de manière incorrecte.(Comme @Holt dit, la citation semble être le contraire.)
"les deux valeurs sont équivalentes, mais pas l'égalité" signifie qu'ils ont la même valeur lors de la comparaison, mais ils migth être différents objets à certains autres aspects.
par exemple
std::max(a, b)
a retournera
, sia
etb
sont-elles équivalentes?a
etb
sont équivalentes, alors!(a < b) && !(b < a)
est vrai, alorsa < b
etb < a
sont fausses, alors... ?