Search code examples
c++functionpointersparameterization

Parameterizing a function using a struct


The code below does not compile. The function foo takes a function pointer f as an argument, and f strictly takes one int as argument and returns an int. In this example, foo always invokes f with the argument 3. I would like to pass a function to foo so that when f(3) is evaluated, it's evaluated in conjunction with some other parameter; however, I can't pass a function with 2 ints as arguments to foo (this problem is an analogy for a real problem).

#include <iostream>

void foo(int(*f)(int))
{
  std::cout << f(3) << std::endl;
}

struct plusX
{
  plusX(int x_) : x(x_) {}
  int x;
  int plus(int y)
  {
    return x + y;
  }
};

int main()
{
  plusX px4(4);
  foo(&px4.plus);  // ERROR!
}

ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&plusX::plus'


Solution

  • Two solutions. The first solution doesn't require refactoring code if existing code uses functions.

    1) Using functors:

    #include <iostream>
    
    template<typename F>
    void foo(F&& f)
    {
      std::cout << f(3) << std::endl;
    }
    
    struct my_functor
    {
      my_functor(int x_) : x(x_) {}
      int operator()(int y)
      {
        return x + y;
      }
      int x;
    };
    
    int main()
    {
      my_functor f(4);
      foo(f);
    }
    

    2) Using std::function and std::bind

    #include <iostream>
    #include <functional>
    
    void foo(const std::function<int(int)>& f)
    {
      std::cout << f(3) << std::endl;
    }
    
    int add(int x, int y)
    {
      return x + y;
    }
    
    int main()
    {
      std::function<int(int)> f_binded = std::bind(add, 4, std::placeholders::_1);
      foo(f_binded);
    }