Error with Address of Parenthesized Member Function

Error with address of parenthesized member function

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!

Understanding error with taking address of non-static member to form pointer to member function?

Pointers to non-static member functions cannot be converted to plain function pointers. A void (MyClass::*)() requires a MyClass object to operate on. Raw pointers can't hold any sort of state though, so there's no way for a void(*)() to store the information about which MyClass object to operate on.

Luckily, the standard library has a class template designed for just this purpose: std::function. std::function is a more-or-less drop-in replacement for raw function pointers, but it can hold any type of callable object that's compatible with a given signature. That means it can hold the state required to call back to a specific instance of a class:

class State {
private:
std::function<void()> on_enter;
std::function<void()> func;
std::function<void()> on_exit;

public:
State(std::function<void()> on_enter, std::function<void()> func, std::function<void()> on_exit)
: on_enter{std::move(on_enter)},
func{std::move(func)},
on_exit{std::move(on_exit)}
{}

void do_something() {
on_enter();
// stuff
func();
// more stuff
on_exit();
}
};

class MyClass {
private:
void func_on_enter() {}
void func() {}
void func_on_exit(){}

State state_a;

public:
MyClass()
: state_a([this]() { func_on_enter(); },
[this]() { func(); },
[this]() { func_on_exit(); })
{}
};

Live Demo

Here, instead of passing pointers to your member functions directly, I've wrapped them in lambdas that capture the this pointer of the object to be called back. Now the State object is able to call those members, and they know which instance of MyClass to operate on.

Be careful about object lifetime though. Since state_a holds pointers back to its MyClass instance, you'll need to ensure MyClass's copy/move constructor and assignment operators do the right thing. The default implementations provided by the compiler aren't sufficient.

error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function

The error message is very clear.

ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Transmitter::sender' [-fpermissive]

From expr.unary.op

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. [ Note: That is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member”. Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” ([conv.func]). Nor is &unqualified-id a pointer to member, even within the scope of the unqualified-id's class. — end note ]

You need to use:

    std::thread t(&Transmitter::sender, this, some_variables);

See this demo

Why must I use address-of operator to get a pointer to a member function?

auto p1 = &f;     // ok
auto p2 = f; // ok

The first is more or less the right thing. But because non-member functions have implicit conversions to pointers, the & isn't necessary. C++ makes that conversion, same applies to static member functions.

To quote from cppreference:

An lvalue of function type T can be implicitly converted to a prvalue
pointer to that function. This does not apply to non-static member
functions because lvalues that refer to non-static member functions do
not exist.

Why can't you get pointer-to-member from unqualified member function name in C++11?

pointer-to-member is rare enough to allow special treatment and not necessarily the most economic one. It was decided that the only accepted form is the one quoted in the error message. That form does not clash with anything else under any circumstances. And prevents ambiguity of more lax forms were allowed.

Practice shows little awareness of PTMFs, and the fact they fundamentally differ from functions. f or &f is likely a request for a normal function. One that can't be served for a nonstatic member. And those who actually mean PTMF say so adding the &X:: part.

Strange C++ rule for member function pointers?

This is just a personal opinion.
If &(qualified-id) is allowed as &(unary-expression),
qualified-id has to be an expression, and an expression is expected to have a type
(even if it is incomplete).
However, C++ didn't have a type which denotes a member, had only
a pointer to member.
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 );
}

In order to make &(qualified-id) be valid, the compiler has to hold
a member type internally.
However, if we abandon &(qualified-id) notation, the compiler doesn't need
to handle member type.
As member type was always handled in the form of a pointer to it,
I guess the standard gave priority to simplify the compiler's type
system a little.

Why does taking a member function pointer value requires class name qualification even from inside of the class?

Pointers and pointer to members are distinct types, we can see that from section the draft C++ standard section 3.9.2 [basic.compound] which includes a compound type for pointer as well as pointer to non-static class member and notes:

Static class members are objects or functions, and pointers to them
are ordinary pointers to objects or functions

This issue with this is I think well described in this quote in an answer from Johannes from the Annotated C++ Reference Manual(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::*'
}

In particular these lines:

int B::* p = &B::i; // OK

and:

p = &i; // error: '&i'means '&this->i' which is an 'int*'

demonstrate the difference between the qualified and the unqualified name.



Related Topics



Leave a reply



Submit