Why write `!!x`, when `x` will do?

Viewed 263

I often see experienced programmers write !!x, even though the expected expression is a Boolean (i.e., zero or not zero) and not an integer.

For example, a line from boost:

BOOST_ASSERT(!!p); // where `p` is a pointer

What's the point of !!p when just p will do?

What I understand by a Boolean parameter is an expression converted to a value of integral type, and the value is compared against zero, explicitly or implicitly (with if or its ternary operator equivalent).

Thus, anything that takes a Boolean and expects only 0 or 1 is wrongly implemented, if my understanding of Boolean is correct.

For clarification: it's obvious that ! converts to bool; the question is explicitly asking for why.

2 Answers

By default, BOOST_ASSERT(expr) expands to assert(expr). That C++ assert function takes a scalar argument, not bool. Thus, your statement, "the expected expression is a boolean," is not correct.

Classes in C++ can implement operator bool(); the basic_stream classes are examples of such: assert(std::cin) will not work. The !! operator forces the use of std::cin::operator bool(), and bool after !! will be evaluated to int 0 or 1. This is shorter than assert(bool(std::cin)).


If I were a boost author, I would expand BOOST_ASSERT(expr) to assert(!!(expr)) - as is done for ( BOOST_LIKELY(!!(expr)) ? ((void)0) ).

Closely related to the question

  1. Warnings.
    Some compilers issue warnings.
  2. Overflow of the integer storing the Boolean.
    I'll just quote the comment mentioning the behaviour

The compiler would treat the values the same either way if it's only used as an operand to an if or &&, but using !! may help on some compilers if if (!!(number & mask)) gets replaced with bit triggered = !!(number & mask); if (triggered); on some embedded compilers with bit types, assigning e.g. 256 to a bit type will yield zero. Without the !!, the apparently-safe transformation (copying the if condition to a variable and then branching) won't be safe.

Related

  1. Some consider defining operator bool() to be "unsafe". And to have an idiomatical way to convert to bool, they define bool operator !().
    So writing !!obj is to support such users. And it doesn't even hurt to do so!
Related