Semplificare il sovraccarico è sempre una buona cosa?

-1

Nei commenti su In C ++ fai necessità di sovraccaricare l'operatore == in entrambe le direzioni? Il narratore si entusiasma dell'overloading semplificato fornito in c ++ 20 con l'operatore <=> .

That's why operator <=> generates so much excitement. Because it can cut down on a lot of boilerplate

Quindi con un passo (e una funzione) creiamo sovraccarichi per meno di maggiore di uguale a e tutte le loro negazioni. Ottimo per qualsiasi cosa con sequenza. Ora sono un tipo contrario e il mio primo pensiero riguarda gli oggetti senza sequenza o la necessità di una sequenza in cui vi è solo il bisogno di test di uguaglianza (o disuguaglianza)? per esempio, diciamo che stiamo facendo il confronto delle unità quindi meter == second dovrebbe ovviamente essere falso, ma che dire di meter < second o anche meter <=> second , visto che sono entrambe sciocchezze, o dovrebbe essere scelto qualsiasi ordine per completare il modello come alfabetico. (che ci darebbe falso e -1)

    
posta hildred 15.11.2018 - 02:19
fonte

4 risposte

8

Quando una nuova funzione viene aggiunta a una lingua, non devi iniziare a usarla alla cieca. Ci saranno spesso casi in cui le vecchie funzionalità sono migliori o l'unica opzione.

L'operatore <=> è molto utile per il caso comune. Ma se non ci si trova nel caso comune, non vi è alcun motivo per utilizzarlo.

    
risposta data 15.11.2018 - 02:41
fonte
5

Prima del C ++ 20, se non ci fosse un ordinamento ragionevole tra un paio di tipi, non implementerebbe un'intera famiglia di operatori: due ciascuno di < , > , <= , >= per A @ B e B @ A .

Dopo C ++ 20, se non esiste un ordinamento ragionevole tra un paio di tipi, non implementare un altro operatore, <=> .

so meter == second should obviously be false

No, meter == second dovrebbe essere un errore di tipo

L'eccitazione deriva dal (piuttosto comune) caso in cui è un ordinamento ragionevole.

    
risposta data 15.11.2018 - 09:38
fonte
3

Come sottolineato in diverse risposte e commenti, il caso meters == seconds non è pertinente alla domanda del titolo.

Quindi, concentriamoci sulla domanda del titolo, che si regge da sola:

Is simplifying overloading always a good thing?

È stato commentato altrove che uno degli argomenti è convenience .

Because it can cut down on a lot of boilerplate

Tuttavia, direi che la praticità è seconda a correctness .

Quando un programmatore è costretto a sovraccaricare ciascuno degli operatori di confronto ordinati pre-C ++ 20, c'è la possibilità che un errore di battitura o un thinko (un cattivo pensiero) possano portare a un'implementazione incoerente.

Ad esempio, all'inizio della mia carriera, una volta ho implementato un operatore strict ordering debole chiamando std::greater_equal , pensando che fosse la scelta naturale poiché era la negazione logica di std::less .

Ecco un esperimento. Prova a memorizzare alcune istanze di questo oggetto in qualsiasi contenitore ordinato in C ++. In alternativa, memorizzali in std::vector , quindi chiama std::sort . Compila ed esegui.

Ciclo infinito, eccezione, eccezione non rilevata o std::abort . Perché?

(Nota) Questi ultimi casi sono possibili in modalità di debug. Nella modalità di rilascio, qualsiasi cosa potrebbe accadere, con il loop infinito molto probabilmente. Un comportamento veramente indefinito diverso dal ciclo infinito si verifica solo se il contenitore è basato sull'albero a causa di un errore di gestione del nodo dell'albero.

Il contratto per std::sort o per gli algoritmi di manutenzione degli ordini in contenitori C ++ dipende da questi operatori di confronto che sono coerenti in ogni momento . Ad esempio, un rigoroso ordine debole deve essere rigoroso in ogni momento. Nota Un errore nel farlo non solo causa un comportamento non specificato; in realtà portano a cose peggiori come potenziali loop infiniti. Poiché le implementazioni degli algoritmi sfruttano il presupposto che gli operatori di confronto definiti dall'utente devono essere coerenti, tale incoerenza non è affatto tollerata. Prevenire il risultato peggiore dall'implementazione non conforme impone un costo di runtime su tutto il software, cosa che infastidisce i programmatori esperti perché i programmatori esperti non commettono questo tipo di errori.

(Nota) Specificamente, (A @ B) e (B @ A) non possono essere entrambi vere, quando @ è un ordine debole rigoroso .

Questa è la mia esperienza molti anni fa. Le cose potrebbero essere cambiate; le nuove implementazioni di algoritmi potrebbero avere una migliore difesa integrata contro gli overload degli operatori di confronto non conformi / incoerenti. Ma perché correre il rischio?

    
risposta data 15.11.2018 - 18:41
fonte
3

L'operatore è puntato direttamente sulle classi che hanno un ordinamento rigoroso-debole naturale.

C'è un modo per etichettare ogni istanza di oggetto della classe con un numero naturale, in modo tale che il risultato del confronto di due istanze di un oggetto sia lo stesso del confronto tra le etichette di questi due oggetti.

La tua classe possiede o meno quella proprietà? In caso contrario, non implementare l'operatore.

Modifica

Come è stato sottolineato, < = > L'operatore (in Confronto a tre vie) copre anche Ordini parziali .

Continuerò ad usare cautela e suggerirò di seguire l'ordine Strict-weak il più lontano possibile, ed essere molto chiaro quando l'ordine non lo segue, per fornire la minima sorpresa agli utenti della classe.

Come sempre forniscono agli operatori solo quando è chiaro cosa intendono. Per fare questo, ti basti molto sulle convenzioni stabilite.

Se sei abbastanza fortunato da operare in un nuovo ambiente, fai attenzione a ciò che hai scelto in quanto potrebbe diventare lo standard de facto.

    
risposta data 15.11.2018 - 05:40
fonte

Leggi altre domande sui tag