JonghoKim
JonghoKim

Reputation: 1995

Function pointer to class member function

I want to make function which has function pointer as a parameter.

#include <iostream>
using namespace std;

class test{

public:
    test(){};

    double tt(double input){
        return input;
    };

};

double fptr_test(double (*fptr)(double), double input){
    return fptr(input);
}


int main(){

    test t;
    cout << t.tt(3) << endl;
    cout << fptr_test(t.tt, 3) << endl;  // This line doesn't work
    cout << fptr_test(&test::tt, 3) << endl;  // This line can't compile

    return 1;
}

But it doesn't work. How could I pass class member function as a parameter?

Can I call the member function without instantiation?

Upvotes: 1

Views: 205

Answers (4)

JonghoKim
JonghoKim

Reputation: 1995

Here is a code after modification.

#include <iostream>
using namespace std;

class test{

public:
    test(){};

    double tt(double input){
        return input;
    };

};

double fptr_test(test* t, double (test::*fptr)(double), double input){
    return (t->*fptr)(input);
}

int main(){

    test t;
    cout << t.tt(3) << endl;
    cout << fptr_test(&t, &test::tt, 3) << endl;

    return 1;
}

Upvotes: 0

Slava
Slava

Reputation: 44278

What you probably want is this:

#include <iostream>
#include <functional>
using namespace std;

class test{

public:
    test(){};

    double tt(double input){
        return input;
    };

};

double fptr_test( std::function<double(double)> func, double input){
    return func(input);
}


int main(){
    using namespace std::placeholders;

    test t;
    cout << t.tt(3) << endl;
    cout << fptr_test( std::bind( &test::tt, t, _1 ), 3) << endl;

    return 0;
}

Btw - when your program finishes correctly you suppose to return 0 from main()

Upvotes: 1

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 154035

A function pointer and a member function pointer have incompatible types. For example, the type of &test::tt is

double (test::*)(double)

rather than

double (*)(double)

The reason for this difference is that a [non-static] member function has a hidden parameter: the pointer to the object the member function is applied, too, i.e., this. The way to a normal function pointer out of a member function is to delegate via a function which supplies the this pointer and, thus, takes an extra argument.

In C++ it is much more useful to not take function pointers as arguments to functions which can be customized by a function but rather to take a function object. This approach comes in two flavors:

  1. The fast approach is to make the function object type a template argument and to just pass whatever function object you got directly. For example, you fptr_test() would look like this:

    template <typename Fun>
    double fptr_test(Fun fun, double input) {
        return fun(input);
    }
    

    The implicit concept used is a function callable with a double argument which yields are result convertible to double.

  2. Especially when the functions being called need to be compiled separately, using a template for each kind of function object isn't viable. In that case it is much more reasonable to use a type-erased representation, i.e., std::function<...>, e.g.:

    double fptr_test(std::function<double(double)> fun, double input) {
        return fun(input);
    }
    

In both cases the function object takes just one argument while your member function takes two: the object to call the function on and the double argument. You'd std::bind(...) the first argument to an object and pass the resulting object to fptr_test():

  test object;
  std::cout << fptr_test(std:bind(&test::tt, &object, std::placeholders::_1), 3) << '\n';
  std::cout << fptr_test([&](double input){ return object.tt(input); }, 3) << '\n';

The code uses two separate approaches to bind the object: the first uses std::bind() while the second uses a lambda function. Both of these calls should work with both of the implementation of fptr_test() provided.

Upvotes: 3

Deduplicator
Deduplicator

Reputation: 45704

If you want to pass a pointer to a member-function, you need to use a member-function-pointer, not a pointer for generic free functions and an object to invoke it on.

Neither is optional.

double fptr_test(test& t, double (test::*fptr)(double), double input){
    return t.*fptr(input);
}

// call like this:
fptr_test(&test::tt, 3); // Your second try

Upvotes: 4

Related Questions