I understand what a double exclamation mark does (or I think I understand) but I am not sure how it is defined on a random object. For example in the code snippet below:
!!
is not a single token in C++ and simply resolves to applying the !
operator twice.
As a
is a pointer and not an object of class type the !
cannot be overloaded. It is defined to return true
if a
is a null pointer and false
otherwise.
The second application of !
simply negates the result of the first !
.
The expression !!a
is equivalent to a != 0
.
Don't think of it as "double exclamation mark", think of it as two separate operators, one running on the result of the other.
For all primitive types, it will "work". !a
is equivalent to a == 0
, so !!a
is equivalent to !(a == 0)
, which in turn is equivalent to a != 0
.
For user-defined types, it won't compile unless they overload operator !
. But obviously, in this case, the behaviour could be almost anything.
bool result = true;
result = !!result; // result = true, e.g. !result is false, !!result is !false.
There is no "!!" operator, so in fact, the statement is equivalent to:
hasSolution = !(!a);
So first, operator!() is called on expression "a", then another operator!() is called on the result. In the case of our code, "a" is a pointer to Assignement. C++ defines a special case for using operator!() on a pointer type: it returns a bool which is true if the pointer is null and false otherwise. In short, the same as the expression (a == 0). Calling operator!() on the result of (!a), which is a bool, simply reverts the result, i.e. returns true if (!a) is false and false if (!a) is true.
So in conclusion, (!!a) return the same result as (a != 0). This is because "a" is a pointer.
The code is horribly complicated. In reality, you want to test whether the getAssigment
method is successful and whether the assigned pointer is non-null.
The code tests that, albeit in a convoluted fashion, taking advantage of weak typing, rather than trying to embrace explicitness and C++’ strong typing. As a consequence, it’s not idiomatic C++ and rather harder to understand than necessary.
In particular, don’t use !!a
in C++. This is an established idiom in weakly-typed languages such as JavaScript to coerce a value into a boolean type. But in C++, this is not commonly used.
It’s not clear what the code does since hasSolution
isn’t defined or used. However, I suspect that the code is supposed to be equivalent to the following:
Assignment *a;
return getAssignment(query, a) and a == nullptr;
(Before C++11, you need to write 0
instead of nullptr
.)
However, this code still reveals a bad design: why is a
passed by reference? Why isn’t it the return value? Worse, a
is never used, so unnecessary. If a
is indeed unnecessary, it should be left out completely. If it’s necessary, it should be the return value. In other words, the prototype of getAssignment
should be as follows:
Assignment* getAssignment(the_type_of_query query);
And it should be used simply as follows:
Assignment* a = getAssignment(query);
Furthermore, I suspect that this code actually assigns memory ownership to the raw pointer a
. This is strongly discouraged in modern C++. Either use no pointers or a smart pointer.
The easiest way to remember double-negation !!a is to narrow a!=0 to 1 and a==0 to 0. Which is in boolean context (i.e. C++) true or false.