I want to use the C11 _Generic
keyword to fill an union according to the static type, like:
typedef union {
double d;
long l;
const char*s;
void*p;
} ty;
#define make_ty(X) _Generic((X), \
double: (ty){.d=(X)}, \
long: (ty){.l=(X)}, \
const char*: (ty){.s=(X)}, \
default: (ty){.p=(X)})
ty from_double(double x) { return make_ty(x); }
ty from_string(const char*s) { return make_ty(s); }
ty from_long(long l) { return make_ty(l);}
but this does not compile, e.g. GCC 5.3 gives (with gcc -std=c11 -Wall
):
u.c: In function ‘from_double’:
u.c:11:35: error: incompatible types when initializing type ‘const char *’
using type ‘double’
const char*: (ty){.s=(X)}, \
^
u.c:14:41: note: in expansion of macro ‘make_ty’
ty from_double(double x) { return make_ty(x); }
BTW, using gcc -std=c99 -Wall
gives the same error...
Or is _Generic
only useful for tgmath.h
?
I thought that _Generic
chooses the expression according to the compiler-known type, so the non-sensical (ty){.s=(x)}
would be ignored in from_double
....
(if that did work, I would be able to "overload" make_ty
according the static, compiler-known, type of the argument...)
All branches of _Generic
must be valid code, just as much as in something like if (1) { here; } else { there; }
. To have a solution you could take it the other way around. Define functions similar to:
inline ty from_double(double x) { return (ty){ .d = x }; }
for all your cases and then have the macro as:
#define make_ty(X) _Generic((X), \
double: from_double, \
double: from_long, \
...)(X)
With the visibility through inline
compilers are actually able to optimize such code and will usually not pass through calling the function pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With