Pass Member Function as Parameter to other Member Function (C++ 11 <function>)

JohnTravolski picture JohnTravolski · Jun 28, 2017 · Viewed 7k times · Source

Let's say that I have a class with three member functions, as follows:

#include <iostream>
#include <functional>

class ClassName
{
  public:
    double add(double a, double b);
    double intermediate(double a, double b, std::function<double (double,double)> func);
    double combiner(double a, double b);
};

double ClassName::add(double a, double b)
{
  return a+b;
}

double ClassName::intermediate(double a, double b, std::function<double (double,double)> func)
{
  return func(a, b);
}

double ClassName::combiner(double a, double b)
{
  return intermediate(a, b, add);
}

int main()
{
  ClassName OBJ;
  std::cout << OBJ.combiner(12, 10);
}

What I'm wanting to do is pass the member function "add" to the member function "intermediate" which is then called by "combiner." However, I don't think that I'm using the right syntax, because when I attempt to compile this, I get an error saying "non-standard syntax; use '&' to create a pointer to member." I'm not quite sure what's going wrong, because this method works perfectly if these functions are not member functions in a class (just regular functions defined in the namespace). So is it possible to pass a member function to another member function?

Answer

songyuanyao picture songyuanyao · Jun 28, 2017

ClassName::add is a non-static member function, an instance of ClassName is needed for it to be called on; it can't be used as the argument for std::function<double (double,double)> directly.

You can use lambda and capture this (as @Igor Tandetnik commented):

return intermediate(a, b, [this](double x, double y) { return add(x, y); } );

or use std::bind and bind this pointer:

return intermediate(a, b, std::bind(&ClassName::add, this, _1, _2));

or make ClassName::add a static member function or a non-member function (it could be because it doesn't use any members of ClassName). e.g.

class ClassName
{
  public:
    static double add(double a, double b);
    ...
};