Strange C ++ rule for pointers to a member function?

Possible duplicate:
Error with round member function address

In this recent question, OP ran into a weird situation in C ++, which makes it illegal to accept the address of a member function if that member name is parentheses. For example, this code is illegal:

struct X { void foo(); }; int main() { void (X::* ptr)(); ptr = &(X::foo); // Illegal; must be &X::foo } 

I looked through this and found that it is due to § 5.3.1 / 3 of the C ++ ISO specification, which reads

A pointer to a member is formed only when explicit and used, and its operand is an identifier not enclosed in parentheses [...]

Does anyone have any idea why the specification has this rule? This is specific to member pointers, so I would suspect that there is some grammatical ambiguity that solves this, but I honestly have no idea what it could be.

+19
c ++ language-lawyer pointer-to-member
Aug 20 '11 at 19:51
source share
2 answers

This is just a personal opinion. If &(qualified-id) allowed as &(unary-expression) , the Qualified Identifier must be an expression, and the expression is expected to be of type (even if it is incomplete). However, C ++ did not have a type that denotes a member, only a pointer to an element. For example, the following code cannot be compiled.

 struct A { int i; }; template< class T > void f( T* ); int main() { (void) typeid( A::i ); f( &A::i ); } 

To make &(qualified-id) valid, the compiler must hold on to the type of the element inside. However, if we abandon the notation &(qualified-id) , the compiler does not need to control the type of the element. Since the member type has always been processed as a pointer to it, I believe that the standard gave priority to simplifying the type of system compiler a bit.

+27
Aug 20 2018-11-21T00:
source share

Imagine this code:

 struct B { int data; }; struct C { int data; }; struct A : B, C { void f() { // error: converting "int B::*" to "int*" ? int *bData = &B::data; // OK: a normal pointer int *bData = &(B::data); } }; 

Without a trick with parentheses, you cannot take a pointer directly to data element B (you will need base class throws and playing with this is not nice).




From ARM:

Note that the operator address must be used explicitly to get a pointer to an element; there is no implicit conversion ... If it were, we would have ambiguity in the context of the member function ... For example,

 void B::f() { int B::* p = &B::i; // OK p = B::i; // error: B::i is an int p = &i; // error: '&i'means '&this->i' which is an 'int*' int *q = &i; // OK q = B::i; // error: 'B::i is an int q = &B::i; // error: '&B::i' is an 'int B::*' } 

IS just kept this concept of pre-Standard and explicitly mentioned that parentheses do this so that you don't get a member pointer.

+3
Aug 21 2018-11-21T00:
source share



All Articles