Specify membership of function point when in argument of definition of function?

Hi,
I'm beginning in C++ with someone else's code that I am changing to suit my purpose. After making my changes there are many compile errors. I have worked my way through most, but have had to play around a bit to correctly interpret the way some of the errors display. One error regards a function that has another function as an argument, and it seems when I call that function there is some mismatch between it and the one declared in the header:

code/ceelirf.cpp:362:61: error: no matching function for call to ‘ceelirf::NewtRoot(void (ceelirf::*)(ceelirf::ftuple&, reell, reell, reell), reell&, reell&, reell&)’
code/ceelirf.cpp:289:7: note: candidate is: reell ceelirf::NewtRoot(void (*)(ceelirf::ftuple&, reell, reell, reell), reell&, reell&, reell&)

fyi reell is a defined type, ftuple is structure, and ceelirf is the class. The two strings match except for what's in the parentheses after 'void'. One is 'ceelirf::*' while the other is just '*'. The declaration of NewtRoot in the header file is:

The definition of NewtRoot in .cpp file is:
 
reell ceelirf::NewtRoot(void (*funcd)(ftuple&, reell, reell, reell), reell& tguess,reell& C1,reell& C2)

The call of the function is
 
estSpikeTime[n]= NewtRoot(&ceelirf::FComplex, tguess,C1,C2);

Any ideas as to why I get the compile error? Is it really the mistmatch of the strings that gives the error? That would mean that from a function call of NewtRoot where the argument is a function of a particular class, the compiler is looking for a definition of NewtRoot where the first argument is a function that is also a member of that class. But I thought arguments in function definitions are for defining the type, and a class membership criteria seems extraneous to that purpose. Am I wrong?

Thanks for reading,

Max
Didn't this question already appear somewhere else?

Do you understand the difference between "void (*)(...)" and "void (ceelirf::*)(...)" ? the first is a (global-scope) function pointer, and the second is a (class-specific) member function pointer. The first will allow you to pass the address of any (global) function (that meets the argument restrictions of course), while the second will only allow a method from that particular class to be passed. (iirc back in the bad old days, member functions would pass an invisible "this" pointer as the first parameter, which is why the two cannot be interchanged).
Hi mmay. I seem to not be explaining my problem well. Let's try again.

>>My question is "if, in writing the arbitrary function pointer argument in the definition of the function, the class membership of the function (to which the function pointer points) needs to be defined. E.g.
 
reell ceelirf::NewtRoot(void (*ceelirf::funcd)(ftuple&, reell, reell, reell), reell& tguess,reell& C1,reell& C2)

where funcd is just a place holder. But this doesn't seem right...

I know the difference in member-specific and global function pointers, but the issue is that the syntax of the definition and call of the function that has the function pointer as an argument are consistent with my understanding, so I don't know how to a change them to 'match' the definition of the function and its call, as seen by the compiler. The function that I pass during the call is indeed a class specific function.

Thanks
Last edited on
*codes a quick sample* ... I see... how interesting... this is what I had to do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>

typedef double reell;
typedef std::vector< double > ftuple;

class ceelirf
{
  private:
    ftuple tuple;
    
  public:
    reell NewtRoot( void (*funcd)( ftuple&, reell, reell, reell),
                    reell& tguess, reell& C1, reell& C2 )
    {
      (*funcd)( tuple, tguess, C1, C2 );
      return tguess + C1 + C2;
    };

    static void FComplex( ftuple& a, reell b, reell c, reell d )
    {
      // do something
    };

    void maxtouzel()
    {
      reell estSpikeTime[5];
      int n = 0;
      reell tguess = 0.0;
      reell C1 = 0.0;
      reell C2 = 0.0;
      
      estSpikeTime[n] = NewtRoot( &ceelirf::FComplex, tguess, C1, C2 );
    }
};



int main( int ac, char *av[] )
{
  std::cout << "Hello World" << std::endl;

  return 0;
}


The crucial thing was to make FComplex a _static_ member function, and then there was no more compile error. As far as the "why" is concerned, I'm afraid somebody else will have to answer your curiosity there...

(I _believe_ the problem is tied up somewhere with the function pointer declaration, and using pointers to member functions... a static member function has a different linkage than a normal member function (for starters, it doesn't need a 'this' pointer...)...).

Is it your intent that ceelirf::NewtRoot() should _only_ accept a member function as that first parameter, or would you prefer it to be able to accept any function that meets the parameters?
Last edited on
This also works too:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <vector>

typedef double reell;
typedef std::vector< double > ftuple;

typedef void (*func_ptr)(ftuple&, reell, reell, reell);
    
void FComplex( ftuple& a, reell b, reell c, reell d )
{
  // do something
};



class ceelirf
{
  private:
    ftuple tuple;
    
  public:
    reell NewtRoot( func_ptr funcd, reell& tguess, reell& C1, reell& C2 )
    {
      (*funcd)( tuple, tguess, C1, C2 );
      return tguess + C1 + C2;
    };

    void maxtouzel()
    {
      reell estSpikeTime[5];
      int n = 0;
      reell tguess = 0.0;
      reell C1 = 0.0;
      reell C2 = 0.0;
      
      estSpikeTime[n] = NewtRoot( &FComplex, tguess, C1, C2 );
    }
};



int main( int ac, char *av[] )
{
  std::cout << "Hello World" << std::endl;

  return 0;
}


In this case, hauling the FComplex function out of the class altogether (the typedef is just 'syntactic sugar' for the previous - I was curious whether defining the function pointer prototype outside the class might change the requirements for matching... but obviously not).
Last edited on
And finally, I _thought_ I remembered some warnings about this X)... the following may be a useful read:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html
mmay wrote:
iirc back in the bad old days, member functions would pass an invisible "this" pointer as the first parameter, which is why the two cannot be interchanged
So the prototype can be seen as
1
2
3
4
reell 
ceelirf::NewtRoot(
   void (funcd)(ceelirf*, ftuple&, reell, reell, reell), 
   reell& tguess,reell& C1,reell& C2)
And now it should be obvious why you need to tell the class of the member function.

Also, you need an object in which to perform the method. So ¿how could you make that work with 'global' functions or methods from another class?
Thanks mmay! That site is great, though dense. I can't do static functions so tried your second method, but I think my code has an added complexity that made it not work. I ended up going with a solution that gets around the error I discussed in the first post by using 'this' to make the class-specific distinction of the function pointer within the function e.g. '(this->*funcd)(args)', while explicitly stating the class in the function declaration, definition, and call:

dec.:

reell NewtRoot(void (ceelirf::*funcd)(ftuple&, reell, reell, reell), reell&,reell&,reell&);

def:

reell ceelirf::NewtRoot( void (ceelirf::*funcd)(ftuple&, reell, reell, reell), reell& tguess,reell& C1,reell& C2)

call:

NewtRoot(&ceelirf::FComplex, tguess,C1,C2);

Still have to check but it at least compiles fine. I'll let you know how it goes.

Last edited on
Yeah, if static methods are out (because local state has to be accessed/modified), then you're on a better track.

You may wish to refer to [33.6] though

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.6

to make the syntax a bit easier to read, as well as [33.5]

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5

just to get things going easier. Good luck! (^_^)/
Topic archived. No new replies allowed.