Title
Comparing nullptr with 0
Status
cd2
Section
7.6.9 [expr.rel]
Submitter
Mike Miller

Created on 2009-09-08.00:00:00 last changed 144 months ago

#### Messages

Date: 2010-03-15.00:00:00

[Voted into WP at March, 2010 meeting.]

Date: 2009-10-15.00:00:00

Proposed resolution (October, 2009):

1. Change 7.6.9 [expr.rel] paragraph 2 as follows:

2. The usual arithmetic conversions are performed on operands of arithmetic or enumeration type. Pointer conversions (7.3.12 [conv.ptr]) and qualification conversions (7.3.6 [conv.qual]) are performed on pointer operands (or on a pointer operand and a null pointer constant, or on two null pointer constants, at least one of which is non-integral) to bring them to their composite pointer type. If one operand is a null pointer constant, the composite pointer type is std::nullptr_t if the other operand is also a null pointer constant or, if the other operand is a pointer, the type of the other operand. Otherwise...
3. Change 7.6.16 [expr.cond] paragraph 6 bullet 3 as follows:

• The second and third operands have pointer type, or one has pointer type and the other is a null pointer constant, or both are null pointer constants, at least one of which is non-integral; pointer conversions (7.3.12 [conv.ptr]) and qualification conversions (7.3.6 [conv.qual]) are performed to bring them to their composite pointer type (7.6.9 [expr.rel]). The result is of the composite pointer type.
Date: 2009-09-08.00:00:00

The current wording of the draft does not indicate what is supposed to happen when an rvalue of type std::nullptr_t is compared with an integral null pointer constant. (This could occur, for example, in template code like

```    template<typename T> void f(T t) {
if (t == 0) // ...
}
```

in a call like f(nullptr) -- presumably the body of the template was written before nullptr became available and thus used an integral null pointer constant.) Because an integral null pointer constant can be converted to std::nullptr_t (7.3.12 [conv.ptr] paragraph 1), one might expect that 0 would be converted to std::nullptr_t and the two operands would compare equal, but 7.6.9 [expr.rel] paragraph 2 does not handle this case at all, leaving it as undefined behavior.

The current situation is more well-defined (but perhaps not better) with respect to the conditional operator. 7.6.16 [expr.cond] paragraphs 3-6 make it ill-formed to have std::nullptr_t and 0 as the second and third operands. Again, it's not too hard to imagine a legacy function template like

```    template<typename T> void f(T t, bool b) {
T t = b ? t : 0;
}
```

which would be ill-formed under the current wording of 7.6.16 [expr.cond].

Either 7.6.9 [expr.rel] and 7.6.10 [expr.eq] should be changed to make this combination of operands ill-formed, or those two sections should be changed to give the comparison defined semantics and 7.6.16 [expr.cond] should be changed to make those operands well-formed.

History
Date User Action Args