views:

92

answers:

5

In code below (please see comment):

#include "stdafx.h"

#include <iostream>
using std::cout;

struct Base
{
 void fnc()
 {
  cout << "Base::fnc()";
 }

};

struct Impl
{
 void* data_;
 Impl(void (Base::*fp)())
 {
  fp();//HERE I'M INVOKING IT - I'M DOING SOMETHING WRONG!
 }
};
int _tmain(int argc, _TCHAR* argv[])
{
 return 0;
}  

Error
"Error 1 error C2064: term does not evaluate to a function taking 0 arguments" Why doesn't it work and how to fix it?

+1  A: 

You need a Base to call the function on.

You might be looking for something more like bind() and function<> that will allow you to bind an instance and member function into a functor that can be just called like a function.

Noah Roberts
@Noah Roberts I can't see a point of using pointers to member function in that case. Why wouldn't I use the pointer to my base class and invoke any function without using this pointer to member function?
There is nothing we can do
@There For the same reason, why you would use function pointer. Dynamic binding to a specific method.
Let_Me_Be
@There if you know what function to call inside a class then using object (something.fnc()) is the way to go, but if you don't know the function then you need both the object and pointer to member function (something.*fp()). Those p-to-m-f's are sometimes handy, but are rarely used.
Dialecticus
I certainly would not agree that pointer to member is a rarely used construct. If you're adequately leveraging the STL you're probably using it a lot.
Noah Roberts
`std::for_each(shapes.begin(), shapes.end(), std::mem_fun(`
wilhelmtell
+5  A: 

It doesn't work because fp is not a function pointer but a member pointer.

How to fix it is easy, use it as it should be used: someinstance.*fp();

Let_Me_Be
You could make the function static. Then Base::*fp(); (up vote)
baash05
A: 
typedef  int (MyClass::*memberPointer_t)(int);

...

memberPointer_t mb = &MyClass::function;
MyClass* object = getObject();

int returnValue = (object->*mb)(3);

...

Since it's a pointer to a member function, you must call it on an object and use the ->* or the .* operator to call it.

Vitor Py
A: 

You could benefit from reading this FAQ regarding pointers to member functions. Particularly they strongly recommend you define a macro for these calls:

#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))

yonilevy
+1  A: 

The problem is that you are calling the function as a free function, when it isn't. It's a member function, and you need to call it in the context of an object:

(obj.*f)();

Boost.Bind offers an idiomatic way to tackle this:

#include<boost/bind.hpp>

// ...
Impl i(boost::bind(&Base::fnc, obj));

You can define the Impl constructor like so:

#include<boost/function.hpp>

// ...
Impl(boost::function<void ()> fnc)
{
    fnc();  // boost::bind translates it to obj.fnc()
}

If only the Impl object knows what object to call the function on, then you can use the placeholders of Boost.Bind:

Impl i(boost::bind(&Base::fnc, boost::_1));

And the Impl constructor would then be similar to

Impl(boost::function<void (Base)> fnc, Base& b)
{
    fnc(b);  // boost::bind translates it to b.fnc()
}

Sometimes it's wiser to use templates in the side that accepts the functor:

template<class Op>
Impl(Op fnc) { ... }

because then the client can pass any member function, with or without boost. But the cost is that you might have harder-to-understand compiler error messages.

wilhelmtell