lostbits
lostbits

Reputation: 1064

How do I pass a function as a parameter

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

Answers (5)

πάντα ῥεῖ
πάντα ῥεῖ

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

molbdnilo
molbdnilo

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

Vlad from Moscow
Vlad from Moscow

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

Daerst
Daerst

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

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

Related Questions