The code is correct, the compiler is out of compliance with the standard, which says (section [expr.eq]
, using the wording from C++0x draft n3225, but it should be the same in other versions):
any pointer to member can be compared to a null pointer constant
and
If both operands are null, they compare equal. Otherwise if only one is null, they compare unequal.
relevant definition of null pointer constant (section [conv.ptr]
, the std::nullptr_t
part is new in C++0x):
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
.
and (section [expr.const]
):
A constant expression is an integral constant expression if it is of integral or enumeration type.
NOTE: As an aside, the implementation-defined representation of pointer-to-virtual-member-function usually is an index into the virtual table, which would be 0 in the question. But according to the standard, the expression inside the assert isn't checking if the representation is zero, it's checking against a zero literal -- it is a null pointer check.
And the Apple compiler apparently mixed the two up. If you wanted to test if the representation is zero, you could write assert((intptr_t)p != 0)
-- and that would be completely non-portable.
But the code as written is perfectly portable, to any standard-compliant compiler, and will never assert.
EDIT: And one more citation from the standard, which just repeats what we've already learned (section [conv.mem]
):
A null pointer constant (4.10) can be converted to a pointer to member type; the result is the null member pointer value of that type and is distinguishable from any pointer to member not created from a null pointer constant.