Since you mentioned you're stuck with C++03 the answer is that without changing the signature of method
, you're stuck with some static
tomfoolery:
The gist of what I'm about to do is to mimic a C++11 style lambda for your specific use case (wrapping a call to a const
member function with empty parameter list that returns void
). You could do some work to make this code a little more general.
First I'll post the wrapper code, then I'll break it down:
template<class T, void(T::*PTR)()const, size_t I>
struct bind_member
{
typedef void(*fn_type)();
explicit bind_member(const T* _ptr)
{
ptr = _ptr;
}
static void func(void)
{
(ptr->*PTR)();
}
operator fn_type()
{
return &func;
}
private:
static const T* ptr;
};
template<class T, void(T::*PTR)()const, size_t I>
const T* bind_member<T, PTR, I>::ptr = NULL;
Live Demo
Breakdown
The template arguments on our bind_member
struct (template<class T, void(T::*PTR)()const, size_t I>
) are for
T
is the type of class whose member function pointer we're wrapping. This becomes Myclass
in your example
void(T::*PTR)()const
is the ugly syntax for a const member function pointer on T
. The name of this template argument is PTR
size_t I
is included so that you can have multiple instances of your Myclass
use the same lambda to wrap the same function, only that you'll need to give each instance its own unique id to avoid them stepping on each other's toes. (In our example we only have one instance, so I gave it 0
instead of making some complicated static counter/member id combination).
Within bind_member
we have our constructor that accepts a pointer to an instance of a class. This is solely for setting the static
class member.
Next we have func
, which is the wrapped way we will call Myclass::m
. If m
accepted an int
, then so would func
. Again, you could do some fancy templating to make this all a little more generic.
Now here's the trick:
We provide an implicit conversion of our bind_member
struct to a C-style function pointer, and we do so in the form of
typedef void(*fn_type)();
operator fn_type()
{
return &func;
}
Which works because our func
type is static
so it doesn't require an instance of the class and therefore does not appear as a member function pointer. The typedef
is for convenience, it's specifying the type of func
, which is that it accepts no arguments and returns void
.
Now onto actually calling within Myclass
:
void run()
{
bind_member<Myclass, &Myclass::m, 0> b(this);
measure(b);
}
I provide the template arguments as described above to create an instance of bind_member
, passing this
as an argument so that bind_member
can call the passed function (m
). I can pass &Myclass::m
as a non-type template parameter because function pointers are pointer types, which are integral types, meaning they have addresses, so we can use template parameters to get those addresses.
Finally, we can pass b
to our measure
function and we're done.
Conclusion
Upgrade to C++11 (or above) if you can, and write a lambda like some of the other answers here describe. Otherwise, beg to change the signature of measure
to be templated on a callable, and then we can wrap Myclass::m
a little easier. If all else fails, use the above approach.