Chociaż starałem się dowiedzieć o c ++ operatorów, natknąłem się na dziwny operator porównania na cppreference.com , * w tabeli, która wyglądała tak:
„Cóż, jeśli są to popularne operatory w C ++, lepiej się ich uczę” - pomyślałem. Ale wszystkie moje próby wyjaśnienia tej tajemnicy zakończyły się niepowodzeniem. Nawet tutaj, na przepełnieniu stosu, nie miałem szczęścia w moich poszukiwaniach.
Czy istnieje związek między <=> a C ++ ?
A jeśli tak, to co dokładnie robi ten operator?
* W międzyczasie cppreference.com zaktualizowało tę stronę i teraz zawiera informacje o <=>
operatorze.
bar< foo::operator<=>
jest przykładem tego, jak może być jak<--
operator.Odpowiedzi:
Nazywa się to operatorem porównania trójstronnego .
Zgodnie z propozycją papierową P0515 :
Cppreference mówi:
źródło
<0
”, „porównuje>0
” i „porównuje==0
”, oznaczają<=>
zwroty ujemne, dodatnie lub zerowe, w zależności od argumentów. Podobnie jakstrncmp
imemcmp
.'a' < 'a'
i'c' < 'a'
oba fałszywe,'a' < 'a'
a'a' < 'c'
nie są. W porządkowaniu silnym następują następujące zasady:a != b
→a < b || b < a
operator==(T x, T y) { return !(x < y) && !(y < x); }
ioperator!=(T x, T y) { return (x < y) || (y < x); }
- ah-ha! Oczywiście jest to mniej wydajne niż prawdziwe,==
ponieważ wywołuje porównanie dwukrotnie, ale nadal jest porządne.< 0
jest prawdziwy. Oznacza to, że jeślia < b
wtedy(a <=> b) < 0
zawsze jest to prawda.W dniu 11.11.2017 r. Komitet ISO C ++ przyjął propozycję Herb Suttera dotyczącą trójstronnego operatora porównania <=> „statku kosmicznego” jako jedną z nowych funkcji dodanych do C ++ 20 . W artykule zatytułowanym Spójne porównanie Sutter, Maurer i Brown demonstrują koncepcje nowego projektu. Aby zapoznać się z wnioskiem, oto fragment tego artykułu:
Kategorie porównawcze
Pięć kategorii porównawczych jest zdefiniowanych jako
std::
typy, z których każda ma następujące predefiniowane wartości:Niejawne konwersje między tymi typami są zdefiniowane w następujący sposób:
strong_ordering
z wartościami {less
,equal
,greater
} niejawnie konwertuje do:weak_ordering
o wartościach {less
,equivalent
,greater
}partial_ordering
o wartościach {less
,equivalent
,greater
}strong_equality
o wartościach {unequal
,equal
,unequal
}weak_equality
o wartościach {nonequivalent
,equivalent
,nonequivalent
}weak_ordering
z wartościami {less
,equivalent
,greater
} niejawnie konwertuje do:partial_ordering
o wartościach {less
,equivalent
,greater
}weak_equality
o wartościach {nonequivalent
,equivalent
,nonequivalent
}partial_ordering
z wartościami {less
,equivalent
,greater
,unordered
} niejawnie konwertuje do:weak_equality
o wartościach {nonequivalent
,equivalent
,nonequivalent
,nonequivalent
}strong_equality
z wartościami {equal
,unequal
} domyślnie konwertuje się na:weak_equality
z wartościami {equivalent
,nonequivalent
}Porównanie trójstronne
<=>
Token wprowadzony. Sekwencja znaków<=>
symbolizuje<= >
w starym kodzie źródłowym. Na przykładX<&Y::operator<=>
musi dodać spację, aby zachować swoje znaczenie.Przeciążalny operator
<=>
jest trójstronną funkcją porównania i ma pierwszeństwo wyższe niż<
i niższe niż<<
. Zwraca typ, który można porównać z literałem,0
ale dozwolone są inne typy zwracania, takie jak obsługa szablonów wyrażeń. Wszystko<=>
operatory zdefiniowane w języku i standardowej bibliotece zwracają jeden z 5 wyżej wymienionychstd::
typów kategorii porównawczych.W przypadku typów języków dostępne są następujące wbudowane
<=>
porównania tego samego typu. Wszystkie są constexpr , chyba że zaznaczono inaczej. Tych porównań nie można wywoływać heterogenicznie przy użyciu skalarnych promocji / konwersji.bool
, integralny i typy wskaźnik,<=>
zwrotówstrong_ordering
.<=>
, a wbudowane są heterogeniczneoperator<=>(T*, nullptr_t)
. Jedynie porównania wskaźników do tego samego obiektu / alokacji są wyrażeniami stałymi.<=>
zwracapartial_ordering
i można je heterogenicznie wywoływać, rozszerzając argumenty na większy typ zmiennoprzecinkowy.<=>
zwraca to samo, co typ bazowy wyliczenia<=>
.nullptr_t
,<=>
zwrotówstrong_ordering
i zawsze plonówequal
.T[N] <=> T[N]
zwraca ten sam typ, coT
„s”<=>
i dokonuje porównania leksykograficznego z zastosowaniem elementów. Nie ma<=>
innych tablic.void
nie ma<=>
.Aby lepiej zrozumieć wewnętrzne funkcjonowanie tego operatora, należy zapoznać się z oryginalną papier . Właśnie tego się dowiedziałem za pomocą wyszukiwarek.
źródło
_equality
typy umarły: okazało się, że<=>
gra dobrze z czterema operatorami relacyjnymi, ale nie tak dobrze z dwoma operatorami równości (chociaż istnieje intensywny cukier syntaktyczny na poparcie typowego przypadku, w którym chcesz je wszystkie).Ta odpowiedź stała się nieistotna od czasu zmiany strony, do której się odwołuje
Witryna, do której się odwołujesz, została uszkodzona. Tego dnia było dużo edytowane i różne części nie były zsynchronizowane. Status, na który patrzyłem, to:
U góry strony znajduje się lista istniejących operatorów porównania (w C ++ 14). Nie ma
<=>
tamNa dole strony powinni wymienić tych samych operatorów, ale wygłupili się i dodali tę przyszłą sugestię.
gcc
jeszcze nie wie o tym<=>
(i z-std=c++14
, nigdy nie będzie), więc myśli, że miałeś na myślia <= > b
. To wyjaśnia komunikat o błędzie.Jeśli spróbujesz tego samego za pięć lat, prawdopodobnie otrzymasz lepszy komunikat o błędzie, coś w rodzaju
<=> not part of C++14.
źródło
<=>
operatora etykietą (od C ++ 20), która informuje, w której wersji standardu można się spodziewać. Etykietowanie standardów to konwencja, którą przestrzega cppreference.com. Oczywiście nie masz kompilatora, który powrócił w maszynie czasu, aby go obsługiwać, ale cpprefernce mówi (poprawnie), czego się spodziewać.