Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with address of parenthesized member function

I found something interesting. The error message says it all. What is the reason behind not allowing parentheses while taking the address of a non-static member function? I compiled it on gcc 4.3.4.

#include <iostream>  class myfoo{     public:      int foo(int number){          return (number*10);      } };  int main (int argc, char * const argv[]) {      int (myfoo::*fPtr)(int) = NULL;      fPtr = &(myfoo::foo);  // main.cpp:14      return 0;  } 

Error: main.cpp:14: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&myfoo::foo'

like image 763
Mahesh Avatar asked Aug 20 '11 19:08

Mahesh


2 Answers

From the error message, it looks like you're not allowed to take the address of a parenthesized expression. It's suggesting that you rewrite

fPtr = &(myfoo::foo);  // main.cpp:14 

to

fPtr = &myfoo::foo; 

This is due to a portion of the spec (§5.3.1/3) that reads

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses [...]

(my emphasis). I'm not sure why this is a rule (and I didn't actually know this until now), but this seems to be what the compiler is complaining about.

Hope this helps!

like image 89
templatetypedef Avatar answered Oct 13 '22 09:10

templatetypedef


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 the trick with the parentheses, you would not be able to take a pointer directly to B's data member (you would need base-class casts and games with this - not nice).


From the ARM:

Note that the address-of operator must be explicitly used to get a pointer to member; there is no implicit conversion ... Had there been, we would have an ambiguity in the context of a 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::*' } 

The IS just kept this pre-Standard concept and explicitly mentioned that parentheses make it so that you don't get a pointer to member.

like image 33
Johannes Schaub - litb Avatar answered Oct 13 '22 08:10

Johannes Schaub - litb