Possible casting issue in declaration of function in header file

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
6 replies · 2K views
CAF123
Gold Member
Messages
2,918
Reaction score
87
Hello all, see below for a snippet of a header file, class1.h, and source code file, class1.cpp, adjusted to reproduce the issue I am having. I have declared a series of functions in the .h file and their corresponding definitions in the .cpp file but when I compile I get the error:

class1.cpp:48:57: error: cannot initialize a parameter of type 'double (*)(double, void *)'
with an rvalue of type 'double (class1::*)(double, void *)'
convolute1(lowerBound,split,epsabs,epsrel,toystruct1,&class1::func1);

I think it is to do with how I declare the function convolute1 in the .h file involving the pointer and maybe there is some casting issue. I have tried a few things including making the func1 static but this gives me problems elsewhere in the code (not reproduced in the toy files below) so I was wondering if anyone could see an issue immediately? Thanks!

Header file, class1.h:
C++:
class class1 {
 
  struct toystruct_t {
    double a,b,c;
    };

  double func1(double z, void *p);
  double func2(toystruct_t toystruct);
 
  double convolute1(double lowerBoundary, double upperBoundary, double epsabs, double epsrel, toystruct_t toystruct, double func(double, void *));
    
};

Source code file, class1.cpp:
C++:
#include <iostream>
#include <gsl/gsl_integration.h>
#include <math.h>
#include <complex>
#include "class1.h"

 struct toystruct_t
      {
        double a,b,c;
      };double class1::func1(double z, void *p)
{
   
    return 2.0;   //function here made trival as reproduces error I wish to discuss without adding further complication
}
              
double class1::convolute1(double lowerBoundary, double upperBoundary, double epsabs, double epsrel, toystruct_t toystruct, double func(double, void *))
{
    double result;
    double err;
    double res;
   
    gsl_integration_workspace * coeffIntegralWorkspace = gsl_integration_workspace_alloc (1e8);
    gsl_function F;
    F.params = (void*)(&toystruct);
    F.function = func;
    gsl_integration_qags(&F, lowerBoundary, upperBoundary,
                         epsabs, epsrel, 1e8,
                         coeffIntegralWorkspace, &result, &err);
   
    gsl_integration_workspace_free(coeffIntegralWorkspace);
   
    res = result;
   
    return res;
}

double class1::func2(toystruct_t toystruct1)
{
  double lowerBound = -10.0;
  double upperBound = -4.0;
  double epsabs=1e-3;
  double epsrel=1e-3;

  double res  =
   convolute1(lowerBound,upperBound,epsabs,epsrel,toystruct1,&class1::func1);

  return res;
}

int main(int argc, const char * argv[]) {
    
     std::count << "Hello World"  << std::endl;
  
 }
 
Last edited by a moderator:
Physics news on Phys.org
I might be wrong, but I think the problem comes where you call convolute1() in class1.cpp.
Change the last parameter in this call to get rid of &

C:
double res  =
   convolute1(lowerBound,upperBound,epsabs,epsrel,toystruct1,class1::func1);

The name of a function is an address -- the address of the entry point in the code for that function.
 
  • Like
Likes   Reactions: CAF123
You shouldn't pass a non-static class member function as a parameter, and there is no need to: code inside class1::convolute1() can access the current instance's func1() member as this->func1().

Mark44 said:
The name of a function is an address -- the address of the entry point in the code for that function.
But that address is not what you want for a non-static member function as the code there is not bound to an instance. Non-static member functions should (can?) only be accessed via the object to which they are bound.
 
  • Like
Likes   Reactions: CAF123
I took another look. You can't do this:
CAF123 said:
C++:
    F.params = (void*)(&toystruct);
    // func must be a pointer to an ordinary function, not a (non-static) class member function.
    F.function = func;
    gsl_integration_qags(&F, lowerBoundary, upperBoundary,
                         epsabs, epsrel, 1e8,
                         coeffIntegralWorkspace, &result, &err);

If you want a function that works with an instance of class1 (let's call it class1_obj although that's a terrible name) then you need to pass class1_obj as (part of) F.params which will be passed to your F.function as the params argument. F.function can then do params.class1_obj.func1().
 
  • Like
Likes   Reactions: CAF123
CAF123 said:
class1.cpp:48:57: error: cannot initialize a parameter of type 'double (*)(double, void *)'
with an rvalue of type 'double (class1::*)(double, void *)'
convolute1(lowerBound,split,epsabs,epsrel,toystruct1,&class1::func1);

Have you considered using functors, instead function pointers?
https://stackoverflow.com/a/6451911
 
  • Like
Likes   Reactions: CAF123
CAF123 said:
Hello all, see below for a snippet of a header file, class1.h, and source code file, class1.cpp, adjusted to reproduce the issue I am having. I have declared a series of functions in the .h file and their corresponding definitions in the .cpp file but when I compile I get the error:

class1.cpp:48:57: error: cannot initialize a parameter of type 'double (*)(double, void *)'
with an rvalue of type 'double (class1::*)(double, void *)'
convolute1(lowerBound,split,epsabs,epsrel,toystruct1,&class1::func1);

I think it is to do with how I declare the function convolute1 in the .h file involving the pointer and maybe there is some casting issue. I have tried a few things including making the func1 static but this gives me problems elsewhere in the code (not reproduced in the toy files below) so I was wondering if anyone could see an issue immediately? Thanks!

Header file, class1.h:
C++:
class class1 {
 
  struct toystruct_t {
    double a,b,c;
    };

  double func1(double z, void *p);
  double func2(toystruct_t toystruct);
 
  double convolute1(double lowerBoundary, double upperBoundary, double epsabs, double epsrel, toystruct_t toystruct, double func(double, void *));
 
};

Source code file, class1.cpp:
C++:
#include <iostream>
#include <gsl/gsl_integration.h>
#include <math.h>
#include <complex>
#include "class1.h"

 struct toystruct_t
      {
        double a,b,c;
      };double class1::func1(double z, void *p)
{
 
    return 2.0;   //function here made trival as reproduces error I wish to discuss without adding further complication
}
           
double class1::convolute1(double lowerBoundary, double upperBoundary, double epsabs, double epsrel, toystruct_t toystruct, double func(double, void *))
{
    double result;
    double err;
    double res;
 
    gsl_integration_workspace * coeffIntegralWorkspace = gsl_integration_workspace_alloc (1e8);
    gsl_function F;
    F.params = (void*)(&toystruct);
    F.function = func;
    gsl_integration_qags(&F, lowerBoundary, upperBoundary,
                         epsabs, epsrel, 1e8,
                         coeffIntegralWorkspace, &result, &err);
 
    gsl_integration_workspace_free(coeffIntegralWorkspace);
 
    res = result;
 
    return res;
}

double class1::func2(toystruct_t toystruct1)
{
  double lowerBound = -10.0;
  double upperBound = -4.0;
  double epsabs=1e-3;
  double epsrel=1e-3;

  double res  =
   convolute1(lowerBound,upperBound,epsabs,epsrel,toystruct1,&class1::func1);

  return res;
}

int main(int argc, const char * argv[]) {
 
     std::count << "Hello World"  << std::endl;
 
 }
I *think* (standards have changed rapidly), your last parameter should be declared as ``double (*func) (<etc>)``

Edit: it appears you are also trying to pass a member function as the last parameter. So the prototype is expecting something like a nonmember function, but in the implementation is an actual member function. I think that explains the error message.
 
Last edited:
  • Like
Likes   Reactions: CAF123