views:

615

answers:

4

Today while writing some Visual C++ code I have come across something which has surprised me. It seems C++ supports ++ (increment) for bool, but not -- (decrement). It this just a random decision, of there is some reason behind this?

This compiles:

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

This does not:

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

It's a deliberate feature (http://msdn.microsoft.com/en-us/library/tf4dy80a.aspx)

I suspect there is a lot of MS code somewhere that uses bool++ to force to true (from the days when bool was an int) and it was easier to patch the compiler than the code.

Martin Beckett
You mean ++ on bools is MS specific then? Are you sure?
Suma
Not sure - but I can't find it in the standard
Martin Beckett
Section 5.2.6 and 5.3.2
Jon Hanna
Thanks don't have a paper copy here, and it's amazingly difficult to search for "++" !
Martin Beckett
I searched for "increment" :)
Jon Hanna
+17  A: 

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

5.2.6-2

The operand of postfix -- is decremented analogously to the postfix ++ operator, except that the operand shall not be of type bool. [Note: For prefix increment and decrement, see 5.3.2. ]

And unsurprisingly...

5.3.2-2

The operand of prefix -- is modified by subtracting 1. The operand shall not be of type bool. The requirements on the operand of prefix -- and the properties of its result are otherwise the same as those of prefix ++. [Note: For postfix increment and decrement, see 5.2.6. ]

Also the 5.6.2-1 and 5.3.2-1 mention that ++ for bools shall be true and Annex D-1 says that ++ on bools in deprecated.

Luther Blissett
Anyone know *why*?
BlueRaja - Danny Pflughoeft
@BlueRaja: See Jon Hanna's answer.
Justin Ardini
+31  A: 

It comes from the history of using integer values as booleans.

If x is an int, but I am using it as a boolean as per if(x)... then incrementing will mean that whatever its truth value before the operation, it will have a truth-value of true after it (barring overflow).

However, it's not possible to predict the result of -- given knowledge only of the truth value of x, as it could result in false (if the integral value is 1) or true (if the integral value is anything else - notably this includes 0 [false] and 2 or more [true]).

So as a short-hand ++ worked, and -- didn't.

++ is allowed on bools for compatibility with this, but its use is deprecated in the standard.


Edit: This assumes that I only use x as an boolean, meaning that overflow can't happen until I've done ++ often enough to cause an overflow on it's own. Even with char as the type used and CHAR_BITS something low like 5, that's 32 times before this doesn't work any more (that's still argument enough for it being a bad practice, I'm not defending the practice, just explaining why it works) for a 32-bit int we of course would have to use ++ 2^32 times before this is an issue. With -- though it will only result in false if I started with a value of 1 for true, or started with 0 and used ++ precisely once before.

This is different if we start with a value that is just a few below 0. Indeed, in such a case we might want ++ to result in the false value eventually such as in:

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

However, this example is treating x as an int everywhere except the conditional, so it's equivalent to:

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

Which is different to only using x as a boolean.

Jon Hanna
Excellent one Jon.
Thank you. Great to know I can still give answers people like on this, given how long it is since I've actually written a line of C++ :)
Jon Hanna
But if x were -1 (TRUE in some platforms like VB), ++x would be FALSE.
James Curran
@James, in C and C++ that would be the case I was thinking of when I said ("barring overflow"). Actually in VB any non-zero has truth value TRUE (like in C), but they have -1 rather than 1 as the result of true boolean operations as then NOT(TRUE) is FALSE, NOT(FALSE) is TRUE, x OR TRUE is TRUE, x OR FALSE is x, x AND FALSE is FALSE and x AND TRUE is x, etc using the same operators for boolean and bit-wise operations (since VB assumes twos-complement so -1 is all 1 bits). However, this can cause some strange bugs in VB if the coder doesn't catch that 2 (true) AND 4 (true) results in 0 (false).
Jon Hanna
+5  A: 

Due to historical reasons this was supported. But note that ... The use of an operand of type bool with the ++ operator is deprecated see Section 5.3.2 in the C++ Standard(n3092)

5.3.2 Increment and decrement [expr.pre.incr]

  • The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completely-defined object type. The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field. If x is not of type bool, the expression ++x is equivalent to x+=1 [ Note: see the discussions of addition (5.7) and assignment operators (5.17) for information on conversions. —end note ]
  • The operand of prefix -- is modified by subtracting 1. The operand shall not be of type bool. The requirements on the operand of prefix -- and the properties of its result are otherwise the same as those of prefix ++.
Abhay