Converting C++ Member Functions into Function Objects

C++ Add comments

Let’s say you have a C++ function that takes a function object as a parameter and calls it:

  1. template <typename _Fn>
  2. void call_functor(_Fn fn)
  3. {
  4.     fn();
  5. }

Now let’s say you want to pass a class’s member function to call_functor() above, as in:

  1. class C
  2. {
  3.     void foo() { std::cout << "foo()\n"; }
  4. };
  5.  
  6. C c;
  7. call_functor(/* What do I put here? c.foo and &C::foo don’t work */);

The STL has a pointer-to-member function adapter called std::mem_fun() which almost gets us there. Unfortunately, it doesn’t quite meet our needs because it requires us to pass a pointer to an instance of C, as in:

  1. C c;
  2. std::mem_fun(&C::foo)(&c); // The &amp;c is the problem

However, we can use std::mem_fun() if we could figure out a way to create a new functor around std::mem_fun() with &c bound as its first parameter. Unfortunately, we cannot use the STL binders (std::bind1st and std::bind2nd) because they only work on binary functions, not unary functions.

In the general case, you should use Boost’s very powerful binding library bind. However, let’s write our own simple binder for expository purposes.

First, we need a function, bind(), that returns a function object which binds a parameter, p1, to a unary function object, func. We’ll call the returned function object binder.

  1. template <typename _Func, typename _P1>
  2. inline binder<_Func, _P1> bind(_Func func, _P1 p1)
  3. {
  4.     return binder<_Func, _P1>(func, p1);
  5. }

The class binder should store func and p1 and have an operator() which calls func with p1 as its parameter. For simplicity we’ll assume func returns void:

  1. template <typename _Func, typename _P1>
  2. class binder
  3. {
  4. public:
  5.     binder(_Func func, _P1 p1) :
  6.         func_(func), p1_(p1) {}
  7.     void operator()() const { return func_(p1_); }
  8.  
  9. private:
  10.     _Func func_; // The functor to apply
  11.     _P1 p1_; // The first paramter
  12. };

We can now solve the initial problem by combining our bind() with std::mem_fun():

  1. call_functor(bind(std::mem_fun(&C::foo), &c));

We can make usage a little more convenient by introducing a macro:

  1. #define mem_fun_functor(c, memFn) bind(std::mem_fun(memFn), &c)
  2.  
  3. call_functor(mem_fun_functor(c, &C::foo));

There’s plenty of room for improvements, but it’s amazing what you can do with a little template trickery.

2 Responses to “Converting C++ Member Functions into Function Objects”

  1. fr3@K Says:

    You should be able to call call_functor() with just bind():

    call_functor(boost::bind(&C::foo, &c));

    [Steve] Hence my comment “In the general case, you should use Boost’s very powerful binding library bind.”

  2. fr3@K Says:

    Right. Seems I missed it the first time I read this post.

    My bad.

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in