Possible casting issue in declaration of function in header file

Click For Summary

Discussion Overview

The discussion revolves around a compilation error encountered in C++ related to the declaration and usage of function pointers in a class context. Participants are examining the header file and source code to identify issues with passing member functions as parameters to a function expecting a pointer to a regular function. The scope includes technical explanations and potential solutions related to function pointers and class member functions.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant highlights a compilation error indicating a mismatch between expected and actual function pointer types when calling convolute1.
  • Another participant suggests removing the address-of operator '&' when passing the member function to convolute1, arguing that the function name itself suffices as an address.
  • Some participants assert that non-static member functions cannot be passed directly as function pointers and can only be accessed through an instance of the class.
  • There is a suggestion that if a function needs to work with an instance of the class, the instance should be passed as part of the parameters to the gsl_function structure.
  • One participant proposes considering the use of functors instead of function pointers, although there is uncertainty about their compatibility with gsl_integration_qags.
  • A later reply reiterates the need for the last parameter in convolute1 to be declared as a pointer to a regular function, not a member function, to resolve the error.

Areas of Agreement / Disagreement

Participants express differing views on how to resolve the issue, with no consensus on the best approach. There is agreement that the error arises from attempting to pass a member function where a regular function pointer is expected, but multiple solutions are proposed without a clear resolution.

Contextual Notes

Participants note that the standards for C++ have evolved, which may affect the interpretation of function pointers and member functions. There are also indications that the proposed solutions may have implications for other parts of the code not included in the discussion.

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