Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #118879

Re: Proper cast of function pointers

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>

Show all headers | View raw


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 | NextPrevious in thread | Next in thread | Find similar | Unroll thread


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