34

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'

6
  • 2
    Indeed interesting. I would normally say, that you should not at all be able to take the pointer of a non-static member of a class. Because without the this pointer, it does not make sense to take the pointer. However, why the parentheses make a difference is beyond me... Commented Aug 20, 2011 at 19:46
  • 2
    @Doug It's not quite the same question. There the issue was needing the classname::. Also doesn't answer what I'm most curious about, which is why (in a why was this decided on sense) are the parens disallowed? Commented Aug 20, 2011 at 19:47
  • 2
    @Doug T- I don't think this is a duplicate. The underlying cause of this problem is a weird provision of the spec preventing parenthesized names of class members from being the target of &, while in the question you linked the issue was that the OP was using a regular function pointer instead of a member function pointer. Commented Aug 20, 2011 at 19:47
  • 2
    @Doug T: There's nothing even remotely dupe about that question. Commented Aug 20, 2011 at 20:22
  • 1
    @Arne: It's a pointer-to-member. You bind the this pointer later. Commented Aug 21, 2011 at 13:45

2 Answers 2

30

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!

Sign up to request clarification or add additional context in comments.

8 Comments

Interesting. When this is allowed int a = 20; int *ptr = &(a); , I don't understand the issue with non-static member functions.
@Mahesh- I have no idea! I just asked this as a question: stackoverflow.com/questions/7134261/…
I would still really like to know that the motivation was. I suspect it might have something to do with a method name having no legit meaning until it is either (1) called or (2) referenced, and so they tried to make it as clear as possible which was happening, but I don't really know.
@templatetypedef I feel like that's this question (is how I interpreted it)
-1: Question: "What is the reason behind not allowing parentheses while taking the address of a non-static member function?" Your answer: "it looks like you're not allowed to take the address of a parenthesized expression" Me: ">.<" // It's also a misleading answer because of course int a; cout << &(a); is perfectly valid; this applies only to pointers-to-members.
|
18

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.

2 Comments

Seems like a funny way [for the committee] to resolve the ambiguity.
@Tomalak it seems only natural to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.