Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it always valid C++ to compare a member function pointer with 0?

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?

like image 405
Kovsa Avatar asked Feb 10 '26 16:02

Kovsa


2 Answers

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.

like image 98
Ben Voigt Avatar answered Feb 12 '26 15:02

Ben Voigt


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.

like image 37
AnT Avatar answered Feb 12 '26 16:02

AnT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!