Posso cambiare la precedenza e l'associatività degli operatori in C ++?

4

Come dice il titolo, trovo utile essere in grado di sovraccaricare gli operatori. È possibile anche modificare il modo in cui gli operatori vengono analizzati specificando la precedenza e l'associatività degli operatori sottoposti a override?

    
posta user827992 16.08.2012 - 06:55
fonte

4 risposte

17

No, non puoi farlo ed è una buona cosa. L'overloading dell'operatore ha già un potenziale sufficiente per rendere il codice illeggibile senza poter modificare la precedenza o l'associatività.

Se vuoi farlo, probabilmente stai sfruttando il sovraccarico dell'operatore e dovresti invece utilizzare le normali funzioni.

    
risposta data 16.08.2012 - 21:36
fonte
14

No. Oltre a rendere il codice illeggibile, renderebbe il linguaggio più ambiguo e profondamente dipendente dal contesto perché non saresti in grado di associare i parametri con le chiamate di funzione fino a quando non conoscerai tutti gli operatori disponibili.

Considera l'espressione

a1 + a2 * a3

dove tutti a* vars hanno tipo A e hai sovraccarichi

A operator+(A, A) // low precedence
A operator*(A, A) // high precedence
B operator+(A, A) // high precedence
A operator*(B, A) // low precedence

Questo potrebbe essere interpretato in due modi diversi

operator+(a1, operator*(a2, a3))

o

operator*(operator+(a1, a2), a3)

Con regole di precedenza e associatività globali, il compilatore può impegnarsi per la prima interpretazione durante l'analisi, ma con associatività / precedenza eccessive, non c'è modo di capire come decomporre i token nelle chiamate di funzione finché non si conoscono tutte le firme degli operatori disponibili.

Questo non rende il linguaggio impossibile da analizzare (anche se ci sono più programmi che devono essere rifiutati come non identificabili) ma renderebbe più lento compilare e più difficile da leggere.

    
risposta data 16.08.2012 - 22:49
fonte
5

No. Anche se a prima vista potrebbe sembrare sensato, se ci pensi un po 'di più, diventa fangoso al punto che è una cattiva idea.

Prima nota che la lingua non è definita utilizzando una grammatica delle precedenze, ma un BNF più classico. Non sono sicuro che il comportamento di sizeof o ?: sia descrivibile semplicemente con una nozione di priorità e associatività.

Tuttavia, il problema principale è che stai modificando la priorità e l'associatività degli operatori sovraccaricati , non definendo la priorità e l'associatività dei nuovi operatori utilizzati solo per i tuoi tipi. Vuoi che le tue modifiche siano applicabili per tutti gli usi o solo per il tuo sovraccarico? Probabilmente sarai d'accordo che la prima opzione è una ricevuta sicura per problemi. L'altro non è molto meglio. Come sai che è il tuo sovraccarico che dovrebbe essere preso in considerazione prima di eseguire la risoluzione di sovraccarico, che richiede l'analisi e quindi l'associatività e la priorità da conoscere.

    
risposta data 16.08.2012 - 21:51
fonte
5

Dopo aver letto alcune risposte, penso che, sì, è tempo per me di cercare i voti negativi.

  • << rappresenta lo spostamento di bit con std::ostream ?
  • + rappresenta un'aggiunta aritmetica con std::string ?
  • * rappresenta il dereferenziazione in boost::spirit ?

Nonostante questo fatto ben stabilito, ci sono ancora persone che sostengono che l'operatore di overload rende il codice illeggibile , e quindi non si dovrebbe ... blah blah ... e loro no. .. blah blah ... e permettendo di cambiare la precedenza .

Trovo che questi argomenti siano semplicemente incoerenti.

Gli operatori sono ciò che rende l'entità per formare un'espressione che insieme definisce un'algebra. Se un'entità non è numerica, non è necessario (intendo il bisogno matematico) che una tale algebra debba seguire la stessa regola dei numeri naturali.

Una delle ragioni per cui gli operatori sovraccaricati rendono il codice difficile da leggere è perché sono costretti a rimanere nelle regole semantiche int, anche per le cose che non hanno la semantica di interi e quindi non hanno bisogno della stessa sintassi.

La risposta alla domanda è:

NO : non puoi modificare la precedenza perché la specifica della lingua non lo consente. Punto fermo.

E se vuoi sapere perché, devi guardare a cosa serve la lingua.

C ++ è già un linguaggio complesso da analizzare e tradurre.  Ammettendo "operatori flessibili" (o anche la definizione di funzioni arbitrarie infix, come ** , <> , <-> , ecc.) Il parser di espressioni non può più essere implementato a parte i tipi, e questo è stato sostenuto dal progettista di linguaggio come "caratteristica con compromesso negativo" (costa più dispiegare che il vantaggio che potrà mai dare nel mondo reale). È solo "economia", non "moralità".

Tutto l'aspetto "morale" (non farlo perché mi fa male) non ha nulla a che fare con la lingua e l'abuso dell'operatore (posso anche abusare di for e usarlo invece di if , ma il problema sono io, non la parola chiave for . Non ha senso basarsi sul fatto che non ha senso basare la precedenza delle variabili anche senza conoscerne un uso appropriato, per la semplice ragione che non può esserci un uso - non importa se cattivo o bene - essendo una cosa del genere proibito all'origine.) e sono solo legati al marketing linguistico.

È stato introdotto l'overloading dell'operatore C ++ per consentire agli scienziati di definire i tipi algebrici privati. È normale per loro chiedere maggiore flessibilità nella definizione e nell'uso dei simboli.

Il linguaggio Java è stato definito per standardizzare la codifica attorno a OOP. E poiché non tutti i programmatori sono anche aspiranti ricercatori scientifici, Java ha rimosso una serie di caratteristiche che possono far deviare il linguaggio dal paradigma OOP su cui è stato filosoficamente progettato. E per motivare questo ai neofiti, una religione dogmatica sostenendo che "l'operatore considerava dannoso", "le variabili globali considerate dannose" e così via era distribuito come annuncio ufficiale nelle scuole.

E il bash contro certe pratiche di codifica perfettamente comuni in matematica e scienza è iniziato proprio da lì.

È molto semplice insegnare "no perché è male e ti fa andare al diavolo" invece di fornire e confrontare idee razionali. E il risultato - 20 anni dopo - è che se lo fai, vai davvero all'inferno perché tutti i credenti di religione (che oggigiorno sono una grande quantità di persone) renderanno la tua vita impossibile.

E da quando Java è diventata la prima lingua i neofiti sono esposti (e C ++ alla fine una seconda) ei suoi paradigmi insegnati come dogmi agli studenti, quando quegli studenti diventano programmatori finiscono per applicare quei "dogmi" a qualsiasi cosa da un'innata "estensione ".

Dopo tutto, nessuno può dare una ragione razionale alla sua squadra di calcio preferita. capita di essere quando inizi a seguirlo. Non ci sono "ragioni tecniche". Solo la passione (dogmi) e lo stress da cambiare (i metodi OOP sono forzati anche al di fuori del contesto OOP)

La ragione per cui non puoi cambiare la precedenza è semplicemente che il mondo ritiene che cambiando quel dogma causerà troppo stress a troppi credenti. Ma razionalmente parlando, non c'è motivo per cui tu possa credere in modo diverso e ti faccia definire una lingua con più libertà d'uso.

    
risposta data 07.04.2014 - 09:19
fonte

Leggi altre domande sui tag