L' 11-11-2017 , il comitato ISO C ++ ha adottato la proposta di Herb Sutter per l' operatore di confronto a tre vie <=> "astronave" come una delle nuove funzionalità aggiunte a C ++ 20 . Nel documento intitolato Confronto coerente Sutter, Maurer e Brown dimostrano i concetti del nuovo design. Per una panoramica della proposta, ecco un estratto dall'articolo:
L'espressione a <=> b restituisce un oggetto che confronta <0 se a <b , confronta > 0 se a> be confronta == 0 se aeb sono uguali / equivalenti.
Caso comune: per scrivere tutti i confronti per il tipo X con il tipo Y , con semantica a livello di membro, è sufficiente scrivere:
auto X::operator<=>(const Y&) =default;
Casi avanzati: per scrivere tutti i confronti per il tuo tipo X con il tipo Y , scrivi l' operatore <=> che accetta una Y , puoi usare
= default per ottenere la semantica a livello di membro se lo desideri e restituisce il tipo di categoria appropriato:
- Restituisce un _ordering se il tuo tipo supporta naturalmente < e genereremo in modo efficiente < , > , <= , > = , == e
! = ; Simmetrico ; altrimenti restituisce una _equality e genereremo in modo efficiente == e ! = simmetrici .
- Restituisce strong_ se per il tuo tipo a == b implica f (a) == f (b) (sostituibilità, dove f legge solo lo stato saliente del confronto accessibile utilizzando i membri const pubblici ), altrimenti restituisci
weak_ .
Categorie di confronto
Cinque categorie di confronto sono definite come std::tipi, ciascuna con i seguenti valori predefiniti:
+--------------------------------------------------------------------+
| | Numeric values | Non-numeric |
| Category +-----------------------------------+ |
| | -1 | 0 | +1 | values |
+------------------+------+------------+---------------+-------------+
| strong_ordering | less | equal | greater | |
| weak_ordering | less | equivalent | greater | |
| partial_ordering | less | equivalent | greater | unordered |
| strong_equality | | equal | nonequal | |
| weak_equality | | equivalent | nonequivalent | |
+------------------+------+------------+---------------+-------------+
Le conversioni implicite tra questi tipi sono definite come segue:
strong_orderingcon i valori { less, equal, greater} converte implicitamente a:
weak_orderingcon i valori { less, equivalent, greater}
partial_orderingcon i valori { less, equivalent, greater}
strong_equalitycon i valori { unequal, equal, unequal}
weak_equalitycon i valori { nonequivalent, equivalent, nonequivalent}
weak_orderingcon i valori { less, equivalent, greater} converte implicitamente a:
partial_orderingcon i valori { less, equivalent, greater}
weak_equalitycon i valori { nonequivalent, equivalent, nonequivalent}
partial_orderingcon i valori { less, equivalent, greater, unordered} converte implicitamente a:
weak_equalitycon i valori { nonequivalent, equivalent, nonequivalent, nonequivalent}
strong_equalitycon valori { equal, unequal} converte implicitamente in:
weak_equalitycon valori { equivalent, nonequivalent}
Confronto a tre vie
Il <=>token viene introdotto. La sequenza di caratteri si <=>tokenizza <= >, nel vecchio codice sorgente. Ad esempio, è X<&Y::operator<=>necessario aggiungere uno spazio per mantenere il suo significato.
L'operatore sovraccaricabile <=>è una funzione di confronto a tre vie e ha la precedenza maggiore di <e minore di <<. Restituisce un tipo che può essere confrontato con il letterale 0ma sono consentiti altri tipi restituiti, ad esempio per supportare i modelli di espressione. Tutti gli <=>operatori definiti nella lingua e nella libreria standard restituiscono uno dei 5 std::tipi di categorie di confronto sopra menzionati .
Per i tipi di linguaggio, <=>vengono forniti i seguenti confronti incorporati dello stesso tipo. Tutti sono constexpr , tranne dove diversamente indicato. Questi confronti non possono essere richiamati in modo eterogeneo utilizzando promozioni / conversioni scalari.
- Per
bool, integrale e tipi di puntatore, <=>restituisce strong_ordering.
- Per i tipi di puntatore, le diverse qualifiche cv e le conversioni da derivato a base possono richiamare un built-in omogeneo
<=>, e ci sono eterogenei incorporati operator<=>(T*, nullptr_t). Solo i confronti di puntatori allo stesso oggetto / allocazione sono espressioni costanti.
- Per i tipi a virgola mobile fondamentali,
<=>restituisce partial_orderinge può essere richiamato in modo eterogeneo allargando gli argomenti a un tipo a virgola mobile più grande.
- Per le enumerazioni,
<=>restituisce lo stesso del tipo sottostante dell'enumerazione <=>.
- Per
nullptr_t, <=>ritorna strong_orderinge sempre produce equal.
- Per gli array copiabili,
T[N] <=> T[N]restituisce lo stesso tipo T's <=>comparatore elementwise lessicografico ed esegue. Non ce n'è <=>per altri array.
- Perché
voidnon c'è <=>.
Per comprendere meglio il funzionamento interno di questo operatore, leggere il documento originale . Questo è proprio quello che ho scoperto usando i motori di ricerca.
bar< foo::operator<=>è un esempio di come potrebbe essere come l'<--operatore.