2

I am trying to build a class that has a member function with a method as argument. The methods are defined in inherited classes. I build a minimal example:

#include <iostream>

struct base
{
    base() {}

    int number(int (*f)(int))
    {
        return f(1);
    }
};

struct option1 : base 
{
    int timesTwo(int i){return 2*i;}
    option1() 
    {
        std::cout << number(timesTwo);
    }
};

struct option2 : base
{
    int timesThree(int i){return 3*i;}
    int timesFour (int i){return 4*i;}
    option2() 
    {
        std::cout << number(timesThree);
    }
};

int main()
{
    option1 a; //I would expect this to print "2"
}

The current syntax in the function number is for a general function, but I cannot get it to work for a method of any inherited classes.

RobVerheyen
  • 435
  • 1
  • 3
  • 10

2 Answers2

5

The problem here is that you're passing a pointer to a member function, which is completely different from a pointer to a non-member function (which is what your number function takes as an argument).

You could use std::function and std::bind:

int number(std::function<int(int)> f)
{
    return f(1);
}

...

number(std::bind(&option1::timesTwo, this, _1));

You could also use templates, and extra arguments, like

template<typename T>
int number(T* object, int(T::*f)(int))
{
    return (object->*f)(1);
}

...

number(this, &option1::timesTwo);

Or the simple (but not always correct, depending on situation and use case): Make the callback-function static:

static int timesTwo(int i){return 2*i;}

My recommendation is that you look over the solution using std::function, because then it's easy to call the number function with any type of callable object, like a lambda:

number([](int x){ return x * 2; });
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks! Could you expand on if I should be worried about the solution of just adding `static`? I understand using `std::function` is more general, but I'm fairly sure I will not have to call the function in any other circumstance. – RobVerheyen Nov 12 '15 at 13:54
  • 1
    @RobVerheyen If the function you pass will never access any non-static members in the class it's defined in, then you can make it `static` without worries. – Some programmer dude Nov 12 '15 at 14:09
4

The given error says :

error: reference to non-static member function must be called

You can just add static before your method members.

And I would suggest you to use std::function instead of pointer functions.

A working code :

#include <iostream>
#include <functional>

struct base
{
    base() {}

    int number(std::function<int(int)> f)
    {
        return f(1);
    }
};

struct option1 : base 
{
    static int timesTwo(int i){return 2*i;}
    option1() 
    {
        std::cout << number(timesTwo);
    }
};

struct option2 : base
{
    static int timesThree(int i){return 3*i;}
    static int timesFour (int i){return 4*i;}
    option2() 
    {
        std::cout << number(timesThree); 
    }
};

int main()
{
    option1 a; // now it works
}
coincoin
  • 4,595
  • 3
  • 23
  • 47
  • Thank you. Is there any reason in particular to use `std::function` over the pointer, given that the code will most likely not need any of the above methods again? – RobVerheyen Nov 12 '15 at 13:55
  • 1
    @RobVerheyen You should take a look [there](http://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c) and [there](http://stackoverflow.com/questions/9054774/difference-between-stdfunction-and-a-standard-function-pointer). It is more C++ish but well you can stick with your solution. I think more importantly you should redesign your code. – coincoin Nov 12 '15 at 14:01