In the following code, the assertion is not raised with the Visual Studio compiler, but it is raised when compiling for the iPhone using XCode:
class X
{
public:
virtual void A() {}
};
X x;
void main()
{
// Define a valid member function pointer to X::A.
void (X::*p)() = &X::A;
assert(p != 0);
}
Is this a bug in the compiler? How else can one check for a null pointer in this case?
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.
The iPhone compiler gets it wrong.
Note that equality comparison between member function pointers that point to virtual functions produces unspecified result, i.e. this assertion
assert(&X::A == &X::A);
behaves unpredictably from the formal point of view.
But comparison of a member function pointers with null-pointer constant is strictly defined by the language. The pointer cannot be null in your example, so it shall not compare equal to a null-pointer constant.
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