bool operator ++ e –

Oggi mentre scrivevo un codice di Visual C ++ mi sono imbattuto in qualcosa che mi ha sorpreso. Sembra che il C ++ supporti ++ (incremento) per bool, ma non – (decremento). Si tratta solo di una decisione casuale, o c’è qualche motivo dietro questo?

Questo compila:

static HMODULE hMod = NULL; static bool once = false; if (!once++) hMod = LoadLibrary("xxx"); 

Questo non:

 static HMODULE hMod = NULL; static bool once = true; if (once--) hMod = LoadLibrary("xxx"); 

Viene dalla cronologia dell’uso di valori interi come booleani.

Se x è un int , ma lo sto usando come booleano come per if(x)... allora l’incremento significherà che qualunque sia il suo valore di verità prima dell’operazione, avrà un valore di verità di true dopo di esso (salvo l’overflow ).

Tuttavia, è imansible prevedere il risultato di -- data conoscenza solo del valore di verità di x , in quanto potrebbe risultare false (se il valore integrale è 1) o true (se il valore integrale è qualsiasi altra cosa – in particolare questo include 0 [ false ] e 2 o più [ true ]).

Così come ha funzionato ++ mano corta, e -- no.

++ è consentito sui bool per compatibilità con questo, ma il suo uso è deprecato nello standard.


Ciò presuppone che io usi solo x come booleano, il che significa che l’overflow non può accadere finché non ho fatto ++ abbastanza spesso da causare un overflow da solo. Anche con char come tipo usato e CHAR_BITS qualcosa di basso come 5, questo è 32 volte prima che questo non funzioni più (questo è ancora argomento sufficiente per essere una ctriggers pratica, non sto difendendo la pratica, solo spiegando perché funziona ) per un 32 bit int , ovviamente dovremmo usare ++ 2 ^ 32 volte prima che questo sia un problema. Con -- sebbene risulterà false se avrò iniziato con il valore 1 per true , o iniziato con 0 e usato ++ precisamente una volta prima.

Questo è diverso se iniziamo con un valore che è appena inferiore a 0. In tal caso, potremmo volere che ++ restituisca il valore false , ad esempio in:

 int x = -5; while(++x) doSomething(x); 

Tuttavia, questo esempio considera x come int dappertutto tranne il condizionale, quindi è equivalente a:

 int x = -5; while(++x != 0) doSomething(x); 

Che è diverso dall’usare solo x come booleano.

ISO ANSI IEC 14882 2003 (c ++ 03):

5.2.6-2

L’operando di postfix – viene decrementato in modo analogo all’operatore di postfix ++, con la differenza che l’operando non deve essere di tipo bool. [Nota: per l’incremento e il decremento del prefisso, vedere 5.3.2. ]

E non sorprende …

5.3.2-2

L’operando del prefisso – viene modificato sottraendo 1. L’operando non deve essere di tipo bool. I requisiti sull’operando del prefisso e le proprietà del suo risultato sono altrimenti uguali a quelli del prefisso ++. [Nota: per incrementi e decrementi di postfix, vedere 5.2.6. ]

Anche il 5.6.2-1 e 5.3.2-1 menzionano che ++ per bool deve essere vero e l’Allegato D-1 dice che ++ su bool in deprecato.

A causa di ragioni storiche questo è stato supportato. Nota che … L’uso di un operando di tipo bool con l’operatore ++ è deprecato, vedi Sezione 5.3.2 nello Standard C ++ (n3092)

5.3.2 Incremento e decremento [expr.pre.incr]

  • L’operando del prefisso ++ viene modificato aggiungendo 1 o impostato su true se è bool (questo uso è deprecato). L’operando deve essere un valore modificabile. Il tipo dell’operando deve essere un tipo aritmetico o un puntatore a un tipo di object completamente definito. Il risultato è l’operando aggiornato; è un lvalue, ed è un campo di bit se l’operando è un campo di bit. Se x non è di tipo bool, l’espressione ++ x è equivalente a x + = 1 [Nota: vedere le discussioni di addizione (5.7) e operatori di assegnazione (5.17) per informazioni sulle conversioni. -End note]
  • L’operando del prefisso – viene modificato sottraendo 1. L’operando non deve essere di tipo bool. I requisiti sull’operando del prefisso e le proprietà del suo risultato sono altrimenti uguali a quelli del prefisso ++.
  • Con i vecchi standard (C ++ 98) non è un errore.
  • Con i nuovi standard l’incremento di un booleano è deprecato. (C ++ 11)
  • È ansible utilizzare l’incremento su un valore booleano fino a C ++ 17.