I just found the following paragraphs in c++03 standard draft relevant to pointer to member conversion.
4.11/2 Pointer to member conversions
The code you wrote is perfectly valid. There's nothing wrong with it (aside from the fact that Derived::a
is private). It is well-formed and the behavior is defined (so far). As the quoted portion of the standard says, it is perfectly legal to upcast member pointers using an explicit static_cast
, which is exactly what you are doing. 5.2.9/9 never says that the pointed member has to be present in the base class.
Also, as you correctly quoted from the standard, the presence of the actual member in the object is required later at the moment of dereference of the pointer, not at the moment of initialization. This, of course, depends on the dynamic type of the object used at the left-hand side of member-access operator (->*
or .*
). The type is only known at run-time and thus cannot be checked by the compiler.
This requirement is included as a mere note into 5.2.9/9, but it is reiterated in a more formal form in 5.5/4
4 If the dynamic type of the object does not contain the member to which the pointer refers, the behavior is undefined.
So, for example, in the context of your example the following lines of code are well-formed
Base b;
b.*pa; // 1
Derived d;
d.*pa; // 2
Base *pb = &d;
pb->*pa; // 3
However, the first dereference produces undefined behavior (since object b
does not contain the member), while both the second one and the third one are perfectly legal.