Does the assertion in the following code snippet always hold?
std::less<Object *> lessPtr;
Object * o = new Object();
assert(lessPtr (o, nullptr) == false);
No, you cannot have ordered comparisons of nullptr or other null pointer constants with pointers.
As a reminder, since C++11, NULL can be either an integer literal with value zero, or a prvalue of type std::nullptr_t . Because of this ambiguity, I recommend switching exclusively to nullptr . nullptr will make your code less error-prone than relying on the implementation-defined NULL .
It is always a good practice to assign the pointer NULL to a pointer variable in case you do not have exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NULL is called a null pointer.
Nullptr vs NULLNULL is 0 (zero) i.e. integer constant zero with C-style typecast to void* , while nullptr is prvalue of type nullptr_t , which is an integer literal that evaluates to zero.
This question really boils down to whether the use of the less-than relational operator on pointer types where one operand is a nullptr
will yield the "expected" result; which sadly isn't the case.
The result is unspecified.
Note: Do mind that
std::less
guarantees a total order; meaning that even if the result, when using the function object, is unspecified, it must yield the same unspecified value on each invocation.
5.9p2 Relational operators
[expr.rel]
Pointers to objects or functions of the same type (after pointer conversions) can be compared, with a result defined as follows:
If two pointers
p
andq
of the same type point to the same object or function, or both point one past the end of the same array, or are both null, thenp<=q
andp>=q
both yieldtrue
andp<q
andp>q
both yieldfalse
.If two pointers
p
andq
of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them is null, the results ofp<q
,p>q
,p<=q
, andp>=q
are unspecified.If two pointers point to non-static data members of the same object, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control (Clause 11) and provided their class is not a union.
If two pointers point to non-static data members of the same object with different access control (Clause 11) the result is unspecified.
If two pointers point to non-static data members of the same union object, they compare equal (after conversion to
void*
, if necessary). If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher.Other pointer comparisons are unspecified.
20.8.5p8
Comparison[comparision]
For templates
greater
,less
,greater_equal
, andless_equal
, the specializations for any pointer type yield a total order, even if the built-in operators<
,>
,<=
,>=
do not.
T * p = new T;
T * q = nullptr;
What is the verdict for p < q
?
Since p
and q
don't point to different elements of the same array (including the element one past the last element of an array), and both don't point to non-static data members of the same object; the result when doing p < q
(and p > q
) is unspecified.
bool a = p < q; // unspecified
bool b = p < q; // unspecified
assert (a == b); // can fire
What about std::less
?
However, when using std::less
we are guaranteed a total order - which effectively means that the below assertion cannot fire (standard-20.8.5p8).
std::less<T*> comp;
bool a = comp (p, q); // unspecified
bool b = comp (p, q); // unspecified
assert (a == b); // can not fire
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With