Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #118879
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Newsgroups | comp.lang.c++ |
| Subject | Re: Proper cast of function pointers |
| Date | 2024-04-24 15:10 -0700 |
| Organization | A noiseless patient Spider |
| Message-ID | <86frvawgwj.fsf@linuxsc.com> (permalink) |
| References | <v08672$1jh9c$1@dont-email.me> <v086ut$1jkn4$1@raubtier-asyl.eternal-september.org> <v08ut6$1p6m1$1@dont-email.me> <v0acqb$26rt3$1@raubtier-asyl.eternal-september.org> <v0au56$2amfo$1@dont-email.me> |
Paavo Helde <eesnimi@osa.pri.ee> writes:
> 24.04.2024 10:36 Bonita Montero kirjutas:
>
>> Am 23.04.2024 um 20:33 schrieb Paavo Helde:
>>
>>> The function pointers are cast to a single type so that they can be
>>> stored in a common lookup array. ...
>>
>> Then you'd need additional information to distinguish the different
>> types. If you have sth. like that you could take a variant<>.
>
> Right, the varying part is the number of arguments, which is
> explicitly declared and stored in the array as well (n_pars below). If
> you are interested, the current code (no warnings any more here,
> thanks to Markus!) looks like below. Not sure if changing to a variant
> or void(*)() would make the code better, looks like then I would need
> to add extra casts to all the lines in the table which currently do
> not need any casts.
>
> #include <math.h>
>
> typedef double (*Func)(double);
>
> struct formu_item {
> const char *name;
> Func f; /* pointer to function*/
> int n_pars; /* number of parameters (0, 1, 2 or 3) */
> int varying; /* Does the result of the function vary
> even when the parameters stay the same?
> varying=1 for e.g. random-number generators. */
> };
>
> typedef void (*VoidFunc)();
> typedef double (*DoubleFunc_0_args)();
> typedef double (*DoubleFunc_2_args)(double, double);
>
> Func FuncCast2(DoubleFunc_2_args fp) {
> return reinterpret_cast<Func>(reinterpret_cast<VoidFunc>(fp));
> }
> Func FuncCast0(DoubleFunc_0_args fp) {
> return reinterpret_cast<Func>(reinterpret_cast<VoidFunc>(fp));
> }
> double pi() {
> return 3.1415926535897932384626433832795029;
> }
>
> static const formu_item ftable_static[TABLESIZE]=
> {
> {"exp", exp,1,0},
> {"ln", log,1,0},
> {"sin", sin,1,0},
> {"cos", cos,1,0},
> {"tan", tan,1,0},
> {"asin", asin,1,0},
> {"acos", acos,1,0},
> {"atan", atan,1,0},
> {"atan2", FuncCast2(atan2),2,0},
> {"abs", fabs,1,0},
> {"sqrt", sqrt,1,0},
> {"pi", FuncCast0(pi),0,0},
> //...
> }
The code below uses no casting, and encapsulates the constructors
for 'formu_item's so that the functions are guaranteed to be in
sync with the discriminating member of the struct. The names and
types of members in formu_item have been changed slightly in some
cases, but except for that it should drop in to the existing code
pretty easily. The final function shows how to invoke a function
in the table safely.
I have added a few bits of running commentary.
Code compiles cleanly (if I haven't made any editing mistakes)
with -pedantic -Wall -Wextra, under c++11, c++14, and c++17.
union FuncU {
double (*zero)();
double (*one)( double );
double (*two)( double, double );
double (*three)( double, double, double );
constexpr FuncU( double (*f)() ) : zero( f ) {}
constexpr FuncU( double (*f)( double ) ) : one( f ) {}
constexpr FuncU( double (*f)( double, double ) ) : two( f ) {}
constexpr FuncU( double (*f)( double, double, double ) ) : three( f ) {}
// a member for each kind of function, and
// a constructor for each of the different function kinds
};
typedef enum {
A_ZERO, A_ONE, A_TWO, A_THREE,
// I use an enum rather than an int
} FKind;
struct formu_item {
const char *name;
FKind n_pars;
bool varying;
FuncU fu;
};
// next is the core idea - have a type-safe constructor
// for each of the different kinds of functions
constexpr formu_item
zero_f( const char *name, bool varying, double (*f)() ){
return { name, A_ZERO, varying, FuncU( f ) };
}
constexpr formu_item
one_f( const char *name, bool varying, double (*f)( double ) ){
return { name, A_ONE, varying, FuncU( f ) };
}
constexpr formu_item
two_f( const char *name, bool varying, double (*f)( double, double ) ){
return { name, A_TWO, varying, FuncU( f ) };
}
typedef double (*Fdouble3)( double, double, double );
constexpr formu_item
three_f( const char *name, bool varying, Fdouble3 f ){
return { name, A_THREE, varying, FuncU( f ) };
}
#include <math.h>
static double pi(){
return 3.1415926535897932384626433832795029;
}
static const formu_item ftable_static[]= {
one_f( "exp", 0, exp ),
one_f( "ln", 0, log ),
one_f( "sin", 0, sin ),
one_f( "cos", 0, cos ),
one_f( "tan", 0, tan ),
one_f( "asin", 0, asin ),
one_f( "acos", 0, acos ),
one_f( "atan", 0, atan ),
two_f( "atan2", 0, atan2 ),
one_f( "abs", 0, fabs ),
one_f( "sqrt", 0, sqrt ),
zero_f( "pi", 0, pi ),
// the function table. Note that if the supplied function
// doesn't match the associated constructor then there will
// be a compilation error
};
double
invoke_formula( unsigned k, double a, double b, double c ){
unsigned n = sizeof ftable_static / sizeof ftable_static[0];
if( k >= n ) return 0. / 0.; // k too large => NaN
switch( ftable_static[k].n_pars ){
case A_ZERO: return ftable_static[k].fu.zero();
case A_ONE: return ftable_static[k].fu.one( a );
case A_TWO: return ftable_static[k].fu.two( a, b );
case A_THREE: return ftable_static[k].fu.three( a, b, c );
}
return -1. / 0.; // table messed up => infinity
}
Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-23 14:31 +0300
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-23 13:44 +0200
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-23 21:33 +0300
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 09:33 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 09:36 +0200
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-24 15:32 +0300
Re: Proper cast of function pointers Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-04-24 15:10 -0700
Re: Proper cast of function pointers "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2024-04-24 15:14 -0700
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-25 08:37 +0300
Re: Proper cast of function pointers Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-04-25 15:04 -0700
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-25 11:19 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-25 11:39 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-25 11:48 +0200
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-25 22:22 +0300
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-26 07:52 +0200
Re: Proper cast of function pointers Tim Rentsch <tr.17687@z991.linuxsc.com> - 2024-04-24 14:40 -0700
Re: Proper cast of function pointers Markus Schaaf <mschaaf@elaboris.de> - 2024-04-23 14:23 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-23 16:44 +0200
Re: Proper cast of function pointers Markus Schaaf <mschaaf@elaboris.de> - 2024-04-23 17:00 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 09:55 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 13:11 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 13:15 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 13:10 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 13:23 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 17:06 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 17:59 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 19:36 +0200
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-23 21:50 +0300
Re: Proper cast of function pointers Markus Schaaf <mschaaf@elaboris.de> - 2024-04-23 22:18 +0200
Re: Proper cast of function pointers Markus Schaaf <mschaaf@elaboris.de> - 2024-04-23 22:22 +0200
Re: Proper cast of function pointers Paavo Helde <eesnimi@osa.pri.ee> - 2024-04-23 23:33 +0300
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-23 16:44 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 11:27 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 13:14 +0200
Re: Proper cast of function pointers Bo Persson <bo@bo-persson.se> - 2024-04-24 14:00 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 16:41 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 17:07 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 18:02 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-24 19:36 +0200
Re: Proper cast of function pointers David Brown <david.brown@hesbynett.no> - 2024-04-24 21:18 +0200
Re: Proper cast of function pointers Bonita Montero <Bonita.Montero@gmail.com> - 2024-04-25 09:50 +0200
csiph-web