6
votes
int main() {
    const int x = 0;
    int* y = x;   // line 3
    int* z = x+x; // line 4
}

Quoth the standard (C++11 §4.10/1)

A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; ...

There are four possibilities:

  1. Line 4 is OK, but line 3 isn't. This is because x and x+x are both constant expressions that evaluate to 0, but only x+x is a prvalue. It appears that gcc takes this interpretation (live demo)

  2. Lines 3 and 4 are both OK. Although x is an lvalue, the lvalue-to-rvalue conversion is applied, giving a prvalue constant expression equal to 0. The clang on my system (clang-3.0) accepts both lines 3 and 4.

  3. Lines 3 and 4 are both not OK. clang-3.4 errors on both lines (live demo).

  4. Line 3 is OK, but line 4 isn't. (Included for the sake of completeness even though no compiler I tried exhibits this behaviour.)

Who is right? Does it depend on which version of the standard we are considering?

1
Outside of "Who is right" regarding (3) or (4), an arguably equally compelling question is, who would actually do either, and why?WhozCraig

1 Answers

10
votes

The wording in the standard changed as a result of DR 903. The new wording is

A null pointer constant is an integer literal (2.14.2) with value zero or a prvalue of type std::nullptr_t.

Issue 903 involves a curious corner case where it is impossible to produce the "correct" overload resolution in certain cases where a template parameter is a (possibly 0) integer constant.

Apparently a number of possible resolutions were considered, but

There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.

So, yes, it depends on whether the compiler has implemented the resolution to DR 903 or not.