Pages

std::function for member functions

We can use std::function to work with a member function. We should just specify the class type for the input function in the template for the std::function. In a way, that is an explicit representation of the "this" pointer that would be used internally to access the relative object.

Since it is possible to pass the relative object in three ways (by value, by reference, by pointer) we should also specify that information in the std::function declaration.

If your compiler does not support std::function yet, you could get the same result using boost::function - just changing a couple of lines in the examples:
#include <iostream>

// boost version
//#include "boost/function.hpp"
//using boost::function;

// C++0x version
#include <functional>
using std::function;

namespace
{
   class AClass
   {
   public:
      void doStuff(int i) const
      {
         std::cout << "Stuff done: " << i << std::endl;
      }
   };
}

void function03()
{
   std::cout << "Member function, class object by value" << std::endl;
   function<void(AClass, int)> f1;
   f1 = &AClass::doStuff;
   f1(AClass(), 1);

   std::cout << "Member function, class object by reference" << std::endl;
   function<void(AClass&, int)> f2;
   f2 = &AClass::doStuff;
   AClass ac2;
   f2(ac2, 2);

   std::cout << "Member function, class object by pointer" << std::endl;
   function<void(AClass*, int)> f3;
   f3 = &AClass::doStuff;
   AClass ac3;
   f3(&ac3, 3);
}
The code is based on an example provided by "Beyond the C++ Standard Library: An Introduction to Boost", by Björn Karlsson, an Addison Wesley Professional book. An interesting reading indeed.

2 comments:

  1. For me this code doesn't compile - error C2664:

    'void std::_Func_class<_Ret,`anonymous-namespace'::AClass &,int>::_Set(std::_Func_base<_Ret,`anonymous-namespace'::AClass &,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,`anonymous-namespace'::AClass &,int> *'

    ReplyDelete
    Replies
    1. I have checked on the environment I am using in this moment, GCC 4.8.1 on Linux, and it still works fine.
      I guess from the error code that you have compiled it on some Visual Studio for Windows. It looks like it requires an explicit cast to accept the assignment.
      I see a bug on Visual Studio Connect, id 694400 that looks suspiciously similar to the behavior you describe.
      Please, have a look at that thread for more details.

      Delete