spiegazione - operatori logici c++




Che cos'è l'operatore<=> in C++? (2)

L' 2017-11-11 , 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 . Nell'articolo 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> b e confronta == 0 se aeb sono uguali / equivalenti.

Caso comune: per scrivere tutti i confronti per il tuo tipo X con tipo Y , con semantica membro, basta scrivere:

auto X::operator<=>(const Y&) =default;

Casi avanzati: per scrivere tutti i confronti per il tuo tipo X con il tipo Y , basta scrivere l' operatore <=> che accetta una Y , se lo desideri puoi usare = default per ottenere la semantica membro e restituire il tipo di categoria appropriato:

  • Restituisce un _ordering se il tuo tipo supporta naturalmente < e genereremo in modo efficiente < , > , <= , > = , == e ! = ; altrimenti restituirà una _equality e genereremo in modo efficiente simmetrico == e ! = .
  • 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 tramite i membri const pubblici), altrimenti restituisce weak_ .

Categorie di confronto

Cinque categorie di confronto sono definite come std:: types, ognuna 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 valori { less , equal , greater } si converte implicitamente in:
    • weak_ordering con valori { less , equivalent , greater }
    • partial_ordering con valori { less , equivalent , greater }
    • strong_equality con valori { unequal , equal , unequal }
    • weak_equality con valori { nonequivalent equivalent , equivalent , non equivalent }
  • weak_ordering con valori { less , equivalent , greater } si converte implicitamente in:
    • partial_ordering con valori { less , equivalent , greater }
    • weak_equality con valori { nonequivalent equivalent , equivalent , non equivalent }
  • partial_ordering con valori { less , equivalent , greater , unordered } converte implicitamente in:
    • weak_equality con valori { nonequivalent equivalent , equivalent , non equivalent , non equivalent }
  • strong_equality con valori { equal , unequal } converte implicitamente in:
    • weak_equality con valori { equivalent , non equivalent }

Confronto a tre vie

Viene introdotto il token <=> . La sequenza di caratteri <=> tokenizzata su <=> , nel vecchio codice sorgente. Ad esempio, X<&Y::operator<=> deve aggiungere uno spazio per mantenerne il significato.

L'operatore sovraccaricabile <=> è una funzione di confronto a tre vie e ha una precedenza superiore a < e inferiore a << . Restituisce un tipo che può essere confrontato con lo 0 letterale, ma sono consentiti altri tipi di restituzione tali da supportare i modelli di espressione. Tutti gli <=> operatori definiti nella lingua e nella libreria standard restituiscono uno dei 5 suddetti tipi di categoria std:: comparazione.

Per i tipi di lingua, vengono forniti i seguenti confronti integrati dello stesso tipo <=> . Tutti sono constexpr , tranne dove diversamente indicato. Questi confronti non possono essere invocati in modo eterogeneo utilizzando promozioni / conversioni scalari.

  • Per i tipi bool , integral e pointer, <=> restituisce strong_ordering .
  • Per i tipi di puntatore, le diverse qualifiche cv e le conversioni derivate alla base possono invocare un omogeneo <=> incorporato e sono presenti operator<=>(T*, nullptr_t) eterogenei <=> operator<=>(T*, nullptr_t) . Solo i confronti di puntatori allo stesso oggetto / allocazione sono espressioni costanti.
  • Per i tipi di virgola mobile fondamentali, <=> restituisce partial_ordering e può essere invocato in modo eterogeneo allargando gli argomenti a un tipo di virgola mobile più grande.
  • Per le enumerazioni, <=> restituisce lo stesso del tipo sottostante dell'enumerazione <=> .
  • Per nullptr_t , <=> restituisce strong_ordering e restituisce sempre equal .
  • Per matrici copiabili, T[N] <=> T[N] restituisce lo stesso tipo di T <=> ed esegue un confronto lessicografico elementally. Non ci sono <=> per altri array.
  • Per 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.

Mentre stavo cercando di conoscere gli operatori C ++ , mi sono imbattuto in uno strano operatore di confronto su cppreference.com , * in una tabella che assomigliava a questa:

"Bene, se questi sono operatori comuni in C ++, è meglio impararli", ho pensato. Ma tutti i miei tentativi di chiarire questo mistero non hanno avuto successo. Anche qui, su Stack Overflow non ho avuto fortuna nella mia ricerca.

C'è una connessione tra <=> e C ++ ?

E se c'è, cosa fa esattamente questo operatore?

* Nel frattempo cppreference.com ha aggiornato quella pagina e ora contiene informazioni sull'operatore <=> .


Questo è chiamato operatore di confronto a tre vie .

Secondo la proposta di carta P0515 :

C'è un nuovo operatore di confronto a tre vie, <=> . L'espressione a <=> b restituisce un oggetto che confronta <0 se a < b , confronta >0 se a > b e confronta ==0 se b sono uguali / equivalenti.

Per scrivere tutti i confronti per il tuo tipo, basta scrivere l' operator<=> che restituisce il tipo di categoria appropriato:

  • Restituisce un _ordering se il tuo tipo supporta naturalmente < e genereremo in modo efficiente < , > , <= , >= , == e != ; altrimenti restituirà una _equality e genereremo in modo efficiente == e ! = .

  • Restituisce strong se per il tuo tipo a == b implica f(a) == f(b) (sostituibilità, dove f legge solo lo stato saliente di confronto accessibile utilizzando l'interfaccia const non privata), altrimenti restituisce debole.

Il cppreference.com dice:

Le espressioni dell'operatore di confronto a tre vie hanno il modulo

lhs <=> rhs   (1)  

L'espressione restituisce un oggetto che

  • confronta <0 se lhs < rhs
  • confronta >0 se lhs > rhs
  • e confronta ==0 se lhs e rhs sono uguali / equivalenti.




spaceship-operator