Obtaining a function pointer to a non static member function - c++

Suppose I have a class:
class A {
public:
A();
void myFunc();
};
Then at a different point in the program I create an instance of class A, and attempt to obtain a function pointer to myFunc():
A* a = new A;
//ATTEMPTS AT RETRIVING FUNCTION POINTER FOR A::MYFUNC
std::function<void()> fnptr = a->myFunc;
std::function<void()> fnptr(std::bind(A::myFunc, &a);
But both of these attempts present the error "call to non static member function without object argument"
Perhaps both of these attempts are totally off the mark, but essentially im trying to obtain a function pointer to the myFunc() function in the specific instance of a. Any help on how to do so is appreciated :)

I'm trying to obtain a function pointer to the myFunc() function
Obtaining a pointer to member function for A::myFunc() can be done:
void (A::*memFuncPtr)() = &A::myFunc;
or even better, taking advantage of auto:
auto memFuncPtr = &A::myFunc;
However, to dereference this pointer (i.e., to call the member function it points to), you will eventually need an A object. This object corresponds to the one the member function will be called on.
You can dereference the pointer to member function, memFuncPtr, either in combination with an A object and the .* operator:
A a;
a.*memFuncPtr();
or in combination with a pointer to an A object and the operator ->*:
A *aPtr = new A();
aPtr->*memFuncPtr();
As a result, you would need to keep a reference to the object or a copy of it in order to create std::function<void()> out of this pointer to member function.
std::invoke
Since C++17, you can simply use the std::invoke() function template instead of .* / ->*. It unifies the syntax for the two cases exposed above:
std::invoke(memFuncPtr, a);
std::invoke(memFuncPtr, aPtr);

You need the following syntax:
std::function<void()> fnptr(std::bind(&A::myFunc, a));
You could also use a lambda expression like this:
auto fn = [a] { a->myFunc(); };
Here's a demo.

Related

how to create queue that will hold pointer to function?

I try to make queue that can receive pointer to function - and i can't find how to do it
this is my code
struct TaskElement
{
int id;
std::function<void()> func;
void operator()()
{
func();
}
};
int main()
{
MyMath* myMathElement = new MyMath();
myMathElement->Print_1();
Queue<TaskElement> myQueue;
TaskElement t1;
t1.id = 1;
t1.func = myMathElement->Print_1;
TaskElement t2;
t2.id = 2;
t2.func = &myMathElement->Print_2;
myQueue.push(t1); Error !!! &': illegal operation on bound member function expression
myQueue.push(t2); Error !!! &': illegal operation on bound member function expression
auto rec1 = myQueue.pop();
rec1();
std::cin.get();
}
Non-static member functions needs an object to be called on. By using plain myMathElement->Print_1 you're not providing any object, just a pointer to a member function.
Either use std::bind to provide the object as the first argument to the function:
t1.func = std::bind(&MyMath::Print_1, myMathElement);
Or use lambda expressions:
t1.func = [myMathElement]() { myMathElement->Print_1(); };
As for your errors, either you get them because of some problem in the Queue class (which you haven't shown us), but more likely the errors doesn't come from the push calls but rather from the assignments to the func member.
You should get them from the assignment because they are not valid assignments. You can't use member functions like that, you must use the address-of operator & and full scoping with the class (or structure) instead of an object. As shown above with the std::bind call, you must use &MyMath::Print_1.

Trying to call a member function pointer won't work

I know member function pointers are a bit tricky, and I can call it if the function pointer isn't a member of the class itself, but can't seem to do it if it's a member of the class:
struct Window
{
virtual void handleEvent() {};
void (Window::*pHandleEvent)();
};
int main()
{
Window w;
void (Window::*fnptr)() = &Window::handleEvent;
(w.*fnptr)(); // Works fine calling a local func ptr
w.pHandleEvent(); // Calling its own member pointer doesn't work
// Err: Expression preceding parentheses of apparent call must have
// (pointer-to) function type
(w.*pHandleEvent)(); // Doesn't work
//Err: identifier "pHandleEvent" is undefined
(w.*Window::pHandleEvent)(); // Doesn't work.
// Err: A non-static member reference must be relative to a specific object.
}
You need to specify two Window objects: the one whose pointer to use and the one on which to call the method. If they’re the same, it’s
(w.*w.pHandleEvent)();
Note the precedence: if you instead have A Window::*ptm; and want a member of the A object, it’s (w.*ptm).a_member.
With C++17 you can just rely on std::invoke for all your pointer to member needs:
std::invoke(w.pHandleEvent, w);
First argument is the pointer to member, the second is the object, or a pointer to it. And all the syntactical business is taken care of for you.

How to cast std::make_unique so that I can use the functions declared in the class?

Or do I need to cast std::make_unique into any forms at all?
I have a FOO class with some functions that I can use:
FOO::FOO(const yoo &yoo, float numbers) :
num_to_execute(numbers)
{
...
...
}
void FOO::execute()
{
execute(num_to_execute);
}
In another .cpp, my given codes initated foo using the following method:
new_foo = std::make_unique<FOO>(yoo, number);
(up until now everything is correct). What I want to do is to call execute on my new_foo. I tried with
new_foo.execute();
But it says:
error: 'class std::unique_ptr<WORK::TOBEDONE::FOO>' has no member named 'EXECUTE'
execute should be able to called on member <WORK::TOBEDONE::FOO> but the std::unique_ptr is giving me a hard time to understand what I should do.
new_foo->execute();
unique_ptr behaves like a regular pointer in that sense, and has a operator-> and operator * overloaded.
you use a regular dot (.) to access unique_ptr functions (like std::unique_ptr::get) while using -> and * to access the pointee.
auto str = std::make_unique<std::string>("hello world");
auto i = std::make_unique<int>(5);
str->size();
*i = 4;
str.reset(); //deletes the pointee and make str point to null
i.reset(); //as above

yet another issue with call by value|reference

The question is simple and may has been discussed before, but I could find a clear answer for my case. Assume I pass a pointer object to a function
#include "foo.h"
int main()
{
foo * aFoo = new foo;
bar(aFoo);
delete aFoo;
aFoo = NULL;
return 0;
}
Then the function is written like this
void bar (foo *f)
{
f->insert();
}
The question:
Is that a call by value or call by reference? I know in call by value, there is an overhead for copying the object from main() to bar(). So I want to be sure that is a call by reference.
It is a call by value, where the value of the pointer aFoo is being copied into the function parameter f.
A call by reference is a call where the parameter is a reference, and side-effects on the argument (and not on objects possibly pointed to by that argument) which occur inside the function are visible to the caller when the function returns.
So for instance this is a function accepting a parameter by reference:
void bar(foo*& f)
// ^
// Here you are taking a pointer by reference
While this is a function accepting a parameter by value:
void bar(foo* f)
// ^
// Here you are taking a pointer to foo by value
You are probably puzzled by the fact that taking a foo by reference and writing:
void bar(foo& f)
{
f.insert();
}
Has pretty much the same effect as passing a pointer to the same foo object by value and writing:
void bar(foo* f)
{ // Precondition: f != nullptr
f->insert();
}
However, the two things are conceptually different. While the value/state of the object you passed in the first case can be different when the function returns from the value/state it had before calling the function, in the second case the value of the pointer you provided will be the same as it was before you called bar() - while the object pointed to may have undergone some state change.
Also notice, that a pointer can be null, while a reference is always bound to an object.
In your case, it is call by value in terms of the pointer to Foo formally. But since you pass a pointer to a function instead of the class instance itself, then it is conceptually call by reference in terms of the class instance since the function call does not copy the whole instance but just its pointer.
Foo fooInstance;
// providing a way to point (less formally you can call it refer) to the instance
Foo* fooPointer = &fooInstance;
// this function call is call by value (passing the value of the pointer).
// but you can logically view it as 'call by reference' to fooInstance.
bar(fooPointer);

What are the pointer-to-member operators ->* and .* in C++?

Yes, I've seen this question and this FAQ, but I still don't understand what ->* and .* mean in C++.
Those pages provide information about the operators (such as overloading), but don't seem to explain well what they are.
What are ->* and .* in C++, and when do you need to use them as compared to -> and .?
I hope this example will clear things for you
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let's take a pointer and assign f to it.
pointer somePointer = &X::f;
//now I want to call somePointer. But for that, I need an object
X x;
//now I call the member function on x like this
(x.*somePointer)(); //will call x.f()
//now, suppose x is not an object but a pointer to object
X* px = new X;
//I want to call the memfun pointer on px. I use ->*
(px ->* somePointer)(); //will call px->f();
Now, you can't use x.somePointer(), or px->somePointer() because there is no such member in class X. For that the special member function pointer call syntax is used... just try a few examples yourself ,you'll get used to it
EDIT: By the way, it gets weird for virtual member functions pointers.
For member variables:
struct Foo {
int a;
int b;
};
int main ()
{
Foo foo;
int (Foo :: * ptr);
ptr = & Foo :: a;
foo .*ptr = 123; // foo.a = 123;
ptr = & Foo :: b;
foo .*ptr = 234; // foo.b = 234;
}
Member functions are almost the same.
struct Foo {
int a ();
int b ();
};
int main ()
{
Foo foo;
int (Foo :: * ptr) ();
ptr = & Foo :: a;
(foo .*ptr) (); // foo.a ();
ptr = & Foo :: b;
(foo .*ptr) (); // foo.b ();
}
In a nutshell: You use -> and . if you know what member you want to access. And you use ->* and .* if you don't know what member you want to access.
Example with a simple intrusive list
template<typename ItemType>
struct List {
List(ItemType *head, ItemType * ItemType::*nextMemPointer)
:m_head(head), m_nextMemPointer(nextMemPointer) { }
void addHead(ItemType *item) {
(item ->* m_nextMemPointer) = m_head;
m_head = item;
}
private:
ItemType *m_head;
// this stores the member pointer denoting the
// "next" pointer of an item
ItemType * ItemType::*m_nextMemPointer;
};
When you have a normal pointer (to an object or a basic type), you would use * to dereference it:
int a;
int* b = a;
*b = 5; // we use *b to dereference b, to access the thing it points to
Conceptually, we're doing the same thing with a member function pointer:
class SomeClass
{
public: void func() {}
};
// typedefs make function pointers much easier.
// this is a pointer to a member function of SomeClass, which takes no parameters and returns void
typedef void (SomeClass::*memfunc)();
memfunc myPointer = &SomeClass::func;
SomeClass foo;
// to call func(), we could do:
foo.func();
// to call func() using our pointer, we need to dereference the pointer:
foo.*myPointer();
// this is conceptually just: foo . *myPointer ();
// likewise with a pointer to the object itself:
SomeClass* p = new SomeClass;
// normal call func()
p->func();
// calling func() by dereferencing our pointer:
p->*myPointer();
// this is conceptually just: p -> *myPointer ();
I hope that helps explain the concept. We're effectively dereferencing our pointer to the member function. It's a little more complicated than that -- it's not an absolute pointer to a function in memory, but just an offset, which is applied to foo or p above. But conceptually, we're dereferencing it, much like we would dereference a normal object pointer.
So called "pointers" to members in C++ are more like offsets, internally. You need both such a member "pointer", and an object, to reference the member in the object. But member "pointers" are used with pointer syntax, hence the name.
There are two ways you can have an object at hand: you have a reference to the object, or you have a pointer to the object.
For the reference, use .* to combine it with a member pointer, and for the pointer, use ->* to combine it with a member pointer.
However, as a rule, don't use member pointers if you can avoid it.
They obey pretty counter-intuitive rules, and they make it possible to circumvent protected access without any explicit casting, that is, inadvertently…
Cheers & hth.,
You cannot dereference pointer to members as normal pointers — because member functions require this pointer, and you have to pass it somehow. So, you need to use these two operators, with object on one side, and pointer on another, e.g. (object.*ptr)().
Consider using function and bind (std:: or boost::, depending on whether you write C++03 or 0x) instead of those, though.
Pointer-to-member access operators: .* and ->*
The pointer-to-member access operators, .* and ->*, are for dereferencing a pointer to member in combination with an object and a pointer to object, respectively. This description applies to both pointers to data members and pointers to member functions.
For example, consider the class Foo:
struct Foo {
int i;
void f();
};
If you declare a member pointer, iPtr, to an int data member of Foo:
int Foo::* iPtr;
You can initialize this member pointer iPtr so that it points to the Foo::i member:
iPtr = &Foo::i;
To dereference this pointer, you need to use it in conjunction with a Foo object.
Consider now the object foo and the pointer to object fooPtr:
Foo foo;
Foo* fooPtr = &foo;
Then, you can dereference iPtr in combination with foo or fooPtr:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
Analogously, you can use .* and ->* with pointers to function members. Note however that you will need to enclose them between parentheses because the function call operator, i.e., (), has higher precedence than both .* and ->*:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
To conclude: you need an object to dereference a pointer to a member, and which one you use, either .* or ->* for dereferencing the pointer to member, depends on whether this needed object is directly provided or through an object pointer.
C++17 — Using std::invoke() instead
The use of both operators can be replaced since C++17 by the std::invoke function template. std::invoke provides a unified way of dereferencing member pointers regardless of whether you use them in combination with an object or an object pointer, and also regardless of whether the pointer to member corresponds to a pointer to data member or pointer to member function:
// dereference a pointer to a data member
std::invoke(iPtr, foo) = 0; // with an object
std::invoke(iPtr, fooPtr) = 0; // with an object pointer
// dereference a pointer to a member function
std::invoke(memFuncPtr, foo); // with an object
std::invoke(memFuncPtr, fooPtr); // with an object pointer
This unified syntax corresponds to the ordinary function call syntax, and it may make it easier to write generic code.