Reputation: 1064
Win 7 cygwin gcc 4.8.3 -std=gnu++11
I've researched this on stackoverflow and cplusplus and thought that I'd passed a function as a parameter correctly, even 'elegantly', but it's clear I have misunderstood something. Can anyone explain how to pass a function as an argument correctly, and why what I have won't work?
A single warning is given for the prototype and a single error for the invocation. Changing genX to genY in the comments but both genX and genY have the same warnings/errors.
class MyClass {
typedef double (*func_t)(double sum);
void driver();
double genX(func_t fnc) { };
double genY(double (*funct)(double sum)) { };
// note: no known conversion for argument 1 from
// '<unresolved overloaded function type>' to
// MyClass::func_t {aka double (*)(double)}
double myThingie(double sum) { };
};
void MyClass::driver() {
genX(myThingie);
genY(myThingie);
// no matching function for call to 'MyClass::genX(<unresolved overloaded function type>)'
}
Upvotes: 0
Views: 132
Reputation: 1
"Can anyone explain how to pass a function as an argument correctly, and why what I have won't work?"
You need
typedef double (MyClass::*func_t)(double sum);
// ^^^^^^^^
to declare function pointers for member class functions.
And get their address like
genX(&MyClass::myThingie);
genY(&MyClass::myThingie);
Upvotes: 4
Reputation: 66459
myThingie
is a member function - a pointer to it has the type double (MyClass::*)(double)
.
A "pointer to member" is completely different from a regular pointer, and needs an instance of a suitable class that it can be dereferenced from.
You can either move myThingie
out of the class, making it a "free" function,
class MyClass {
typedef double (*func_t)(double sum);
void driver();
double genX(func_t fnc) { };
double genY(double (*funct)(double sum)) { };
};
double myThingie(double sum) { };
or adjust the types:
class MyClass {
typedef double (MyClass::*func_t)(double sum);
double genX(func_t fnc) { };
double genY(double (MyClass::*funct)(double sum)) { };
double myThingie(double sum) { };
};
void MyClass::driver() {
genX(&MyClass::myThingie); // The "MyClass::" is important here, too.
genY(&MyClass::myThingie);
}
In this case you need to use the "pointer-to-member" dereferencing syntax to call the function.
For instance,
double genX(func_t fnc) { return (this->*fnc)(0.0) };
Upvotes: 0
Reputation: 311136
Try the following
class MyClass {
typedef double (MyClass::*func_t)(double sum);
void driver();
double genX(func_t fnc) { };
double genY(double (MyClass::*funct)(double sum)) { };
// note: no known conversion for argument 1 from
// '<unresolved overloaded function type>' to
// MyClass::func_t {aka double (*)(double)}
double myThingie(double sum) { };
};
void MyClass::driver() {
genX(&MyClass::myThingie);
genY(&MyClass::myThingie);
// no matching function for call to 'MyClass::genX(<unresolved overloaded function type>)'
}
Upvotes: 1
Reputation: 973
Your declarations are stating that the functions expect free function pointers, not member function pointers. Second, you are providing function pointers to myThingie
, which is a member function of MyClass
, without providing an instance. Read up on C function pointer or, if you can, use std::function for a more C++'ish solution.
Upvotes: 1
Reputation: 1
If you insist on passing a (C-like, non-member) function pointer, use (notably for readability) a typedef
(outside of the class
) to declare its signature:
typedef double func_sig_t(double);
then pass a pointer to that, e.g.
double genX(func_sig_t* fnc) { };
However, I would use std::function
double genX(std::function<double(double)>);
it is less cheap, but you could then pass a lambda closure, e.g. call
double t;
double f = genX([=t](double x){return x+t;});
Or do you want to pass pointer to member functions? They have different syntaxes!
Upvotes: 0