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_ordering
con i valori { less
, equal
, greater
} converte implicitamente a:
weak_ordering
con i valori { less
, equivalent
, greater
}
partial_ordering
con i valori { less
, equivalent
, greater
}
strong_equality
con i valori { unequal
, equal
, unequal
}
weak_equality
con i valori { nonequivalent
, equivalent
, nonequivalent
}
weak_ordering
con i valori { less
, equivalent
, greater
} converte implicitamente a:
partial_ordering
con i valori { less
, equivalent
, greater
}
weak_equality
con i valori { nonequivalent
, equivalent
, nonequivalent
}
partial_ordering
con i valori { less
, equivalent
, greater
, unordered
} converte implicitamente a:
weak_equality
con i valori { nonequivalent
, equivalent
, nonequivalent
, nonequivalent
}
strong_equality
con valori { equal
, unequal
} converte implicitamente in:
weak_equality
con 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 0
ma 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_ordering
e 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_ordering
e 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é
void
non 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.