Generics for multiparameter C functions in C11

c c11
Mathuin picture Mathuin · Jun 25, 2013 · Viewed 7.3k times · Source

I understand C11 generics for one-parameter functions, like this: (from here)

#define acos(X) _Generic((X), \
    long double complex: cacosl, \
    double complex: cacos, \
    float complex: cacosf, \
    long double: acosl, \
    float: acosf, \
    default: acos \
    )(X)

But, it seems to be a pain for functions with two arguments, you need to nest calls to _Generic, which is really ugly; Excerpt from the same blog:

#define pow(x, y) _Generic((x), \
long double complex: cpowl, \

double complex: _Generic((y), \
long double complex: cpowl, \
default: cpow), \

float complex: _Generic((y), \
long double complex: cpowl, \
double complex: cpow, \
default: cpowf), \

long double: _Generic((y), \
long double complex: cpowl, \
double complex: cpow, \
float complex: cpowf, \
default: powl), \

default: _Generic((y), \
long double complex: cpowl, \
double complex: cpow, \
float complex: cpowf, \
long double: powl, \
default: pow), \

float: _Generic((y), \
long double complex: cpowl, \
double complex: cpow, \
float complex: cpowf, \
long double: powl, \
float: powf, \
default: pow) \
)(x, y)

Is there a way to have more human being-readable generics for multiparameter functions, like this for instance :

#define plop(a,b) _Generic((a,b), \
      (int,long): plopii, \
      (double,short int): plopdd)(a,b)

Thanks in advance for your replies. The basic idea would be having a macro wrapper for _Generic.

Answer

torek picture torek · Jun 25, 2013

Given that the controlling expression of _Generic is not evaluated, I'd suggested applying some arithmetic operation that does the appropriate type-combining, and switching on the result. Thus:

#define OP(x, y) _Generic((x) + (y), \
    long double complex: LDC_OP(x, y), \
    double complex: DC_OP(x, y), \
    ... )

Of course this only works for certain cases, but you can always expand out those for which the "collapsed" type is not helpful. (This would let one take care of array-N-of-char vs char *, for instance, as with the linked printnl example, and then if the combined type is int, one can go back and check for char and short.)