web-dev-qa-db-fra.com

Pourquoi utiliser «b <a? a: b ”au lieu de“ a <b? b: a ”pour implémenter max template?

Modèles C++ - Le Guide complet, 2e édition introduit le modèle max :

template<typename T>
T max (T a, T b)
{
  // if b < a then yield a else yield b
  return  b < a ? a : b;
}

Et cela explique l'utilisation de “b < a ? a : b” au lieu de “a < b ? b : a”:

Notez que le modèle max () selon [StepanovNotes] renvoie intentionnellement "b <a? a: b ”au lieu de“ a <b? b: a ”pour s'assurer que la fonction se comporte correctement même si les deux valeurs sont équivalentes mais pas égales.

Comment comprendre "even if the two values are equivalent but not equal."? “a < b ? b : a” semble avoir le même résultat pour moi.

153
Nan Xiao

std::max(a, b) est en effet spécifié pour renvoyer a lorsque les deux sont équivalents.

Ceci est considéré comme une erreur par Stepanov et les autres parce qu'il casse la propriété utile qui donne a et b, vous pouvez toujours les trier avec {min(a, b), max(a, b)}; pour cela, vous voudriez que max(a, b) renvoie b lorsque les arguments sont équivalents.

152
T.C.

Cette réponse explique pourquoi le code donné est incorrect du point de vue standard C++, mais hors contexte.

Voir réponse de @T.C. pour une explication contextuelle.


La norme définit std::max(a, b) comme suit [alg.min.max] (l'emphase est à moi):

template<class T> constexpr const T& max(const T& a, const T& b);

Requiert : le type T est LessThanComparable (Tableau 18).

renvoie : la valeur la plus grande.

Remarques : Renvoie le premier argument lorsque les arguments sont équivalents.

Équivalent signifie ici que !(a < b) && !(b < a) est true[alg.sorting # 7] .

En particulier, si a et b sont équivalents, a < b et b < a sont false, la valeur à droite de : être retourné dans l'opérateur conditionnel, donc a doit être à droite, donc:

a < b ? b : a

... semble être la bonne réponse. C'est la version utilisée par libstdc ++ et libc ++ .

Ainsi, les informations contenues dans votre citation semblent erronées par rapport à la norme actuelle, mais le contexte dans lequel elles sont définies peut être différent.

63
Holt

Le point est celui qui devrait être retourné quand ils sont équivalents; std::max doit renvoyer a (c'est-à-dire le premier argument) pour ce cas.

Si elles sont équivalentes, retourne a.

Donc _a < b ? b : a_ devrait être utilisé; Par contre, _b < a ? a : b;_ renverra b de manière incorrecte.

(Comme @Holt l'a dit, la citation semble opposée.)

"les deux valeurs sont équivalentes mais pas égales" signifie qu'elles ont la même valeur lorsqu'elles sont comparées, mais elles peuvent être des objets différents à d'autres égards.

par exemple.

_struct X { int a; int b; };
bool operator< (X lhs, X rhs) { return lhs.a < rhs.a; }
X x1 {0, 1};
X x2 {0, 2};
auto x3 = std::max(x1, x2); // it's guaranteed that an X which cantains {0, 1} is returned
_
21
songyuanyao