Reputation: 1995
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
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
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
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:
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
.
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
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