9

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?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
JohnTravolski
  • 131
  • 1
  • 1
  • 6

2 Answers2

14

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);
    ...
};
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
8

If you truly want to pass the member function, you need a member function pointer

class ClassName
{
   public:
    double add(double a, double b);
    using Combiner = double (ClassName::*)(double, double);
    double intermediate(double a, double b, Combiner);
    double combiner(double a, double b);
};

This will only slightly change the implementation of intermediate and combiner

double ClassName::intermediate(double a, double b, Combiner func)
{
  return (this->*func)(a, b);
}

double ClassName::combiner(double a, double b)
{
  return intermediate(a, b, &ClassName::add);
}
HeroicKatora
  • 958
  • 8
  • 17