Szablony C ++ - kompletny przewodnik, wydanie 2, wprowadza szablon max :
template<typename T>
T max (T a, T b)
{
// if b < a then yield a else yield b
return b < a ? a : b;
}
I wyjaśnia użycie “b < a ? a : b”
zamiast “a < b ? b : a”
:
Zauważ, że szablon max () zgodny z [StepanovNotes] celowo zwraca „b <a? a: b ”zamiast„ a <b? b: a ”, aby upewnić się, że funkcja zachowuje się poprawnie, nawet jeśli dwie wartości są równoważne, ale nie równe.
Jak rozumieć „ even if the two values are equivalent but not equal.
”? “a < b ? b : a”
wydaje się mieć ten sam wynik dla mnie.
a
ib
są równoważne , to!(a < b) && !(b < a)
jest prawda, taka < b
ib < a
oba fałszywe, więc wb < a ? a : b
,b
jest zwracana, co nie jest to, co chcesz ... Ty chcesza < b ? b : a
.a
ab
zstd::addressof
et. glin.a = max(a, b);
(wielokrotnie), możesz nie chcieća
niepotrzebnie wymieniać .a
kopiąa
).std::addressof
to nie ma znaczenia. WłaściwieT max(T a, T b)
to już wiemyaddressof(a) != addressof(b)
.Odpowiedzi:
std::max(a, b)
jest rzeczywiście określona jako zwracana,a
gdy te dwa są równoważne.Uważa to za błąd Stiepanowa i innych, ponieważ łamie podaną użyteczną właściwość
a
ib
zawsze można je posortować{min(a, b), max(a, b)}
; w tym celu chciałbyśmax(a, b)
zwrócić,b
gdy argumenty są równoważne.źródło
{min(a, b), max(b, a)}
?max(a,b)
zwróci wartość „jeśli i tylko”, jeślimin(a,b)
zwraca b i na odwrót, tak że są one wzajemnie odwrotne, a (nieuporządkowany) zbiór{min(a,b), max(a,b)}
jest zawsze równy{a,b}
.min
imax
do wszystkiego poza datownikiem (kluczem sortowania) w tym scenariuszu nie ma sensu. Same zdarzenia (obiekty) nie powinny być nawet porównywalne, jeśli równość nie oznacza zamienności. Jedynym sposobem{min(a, b), max(a, b)}
sprawia żadnego sensu, ponieważ mechanizm sortowania jest jeśli obiekty są wymienne.Ta odpowiedź wyjaśnia, dlaczego podany kod jest nieprawidłowy ze standardowego punktu widzenia C ++, ale jest poza kontekstem.
Zobacz odpowiedź @ TC, aby uzyskać kontekstowe wyjaśnienie.
Standard definiuje
std::max(a, b)
następująco [alg.min.max] ( wyróżnienie moje):Odpowiednik tutaj oznacza, że
!(a < b) && !(b < a)
jest totrue
[alg.sorting # 7] .W szczególności, jeśli
a
ib
są równoważne, obaa < b
ib < a
sąfalse
, więc wartość po prawej:
stronie zostanie zwrócona w operatorze warunkowym, więca
musi być po prawej stronie, więc:... wydaje się być poprawną odpowiedzią. To jest wersja używana przez libstdc ++ i libc ++ .
Tak więc informacje w Twojej wycenie wydają się błędne zgodnie z obecnym standardem, ale kontekst, w którym są zdefiniowane, może być inny.
źródło
X
).a<b
ib<a
oba mogą być fałszywe, ponieważ są nieuporządkowane (jeden lub oba NaN, więc też==
jest fałsz). Można to postrzegać jako rodzaj równoważności. luźno powiązane:maxsd a, b
implementacje instrukcji x86a = max(b,a) = b < a ? a : b
. ( Jaka jest instrukcja, która podaje wartości minimalne i maksymalne FP bez gałęzi na x86? ). Instrukcja utrzymuje operand źródłowy (drugi) w stanie nieuporządkowanym, więc pętla nad tablicą da ci NaN, jeśli były jakieś NaN. Alemax_seen = max(max_seen, a[i])
zignoruje NaNs.Chodzi o to, który należy zwrócić, gdy są one równoważne;
std::max
musi zwrócića
(tj. pierwszy argument) w tym przypadku.Więc
a < b ? b : a
powinno być używane; z drugiej stronyb < a ? a : b;
zwrócib
nieprawidłowo.(Jak powiedział @Holt, cytat wydaje się odwrotny.)
„te dwie wartości są równoważne, ale nie równe” oznacza, że mają tę samą wartość podczas porównywania, ale w niektórych innych aspektach mogą być różnymi obiektami.
na przykład
źródło
std::max(a, b)
musi wrócića
, jeślia
ib
są równoważne?a
ib
są równoważne, to!(a < b) && !(b < a)
jest prawdziwe, więca < b
ib < a
są fałszywe, więc ...?