Possible casting issue in declaration of function in header file

Click For Summary
SUMMARY

The forum discussion addresses a compilation error encountered in C++ when attempting to pass a non-static member function as a function pointer. The error arises from the declaration of the function convolute1 in the header file class1.h, which expects a function pointer of type double (*)(double, void *). The user is advised to remove the address-of operator (&) when passing class1::func1 to convolute1 and to access member functions using this->func1() within the class context.

PREREQUISITES
  • Understanding of C++ class member functions and their access patterns
  • Familiarity with function pointers in C++
  • Knowledge of the GNU Scientific Library (GSL) for numerical integration
  • Basic understanding of C++ compilation errors and debugging techniques
NEXT STEPS
  • Review C++ function pointer syntax and usage
  • Learn about member function pointers and their limitations
  • Explore the GNU Scientific Library (GSL) documentation for integration functions
  • Investigate alternatives to function pointers, such as functors or lambda expressions in C++
USEFUL FOR

C++ developers, particularly those working with numerical methods and integration, as well as programmers debugging compilation issues related to function pointers and class member functions.

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:
Technology 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
  • 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

Similar threads

  • · Replies 2 ·
Replies
2
Views
2K
Replies
6
Views
4K
  • · Replies 2 ·
Replies
2
Views
2K