_Generic to populate some union

I want to use the C11 _Generic keyword to populate a union according to a static type, for example:

 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 it does not compile, for example. GCC 5.3 gives (with gcc -std=c11 -Wall ):

 uc: In function 'from_double': uc:11:35: error: incompatible types when initializing type 'const char *' using type 'double' const char*: (ty){.s=(X)}, \ ^ uc: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 useful only for tgmath.h ?

I thought that _Generic selects the expression according to the known type of compiler, so insensitive (ty){.s=(x)} will be ignored from from_double ....

(if this worked, I could "overload" make_ty according to the static, well-known compiler, the type of the argument ...)

+8
c c11
source share
1 answer

All _Generic branches must be valid, as in if (1) { here; } else { there; } if (1) { here; } else { there; } if (1) { here; } else { there; } . To have a solution, you could do 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 the macro:

 #define make_ty(X) _Generic((X), \ double: from_double, \ double: from_long, \ ...)(X) 

With visibility through inline compilers can actually optimize such code and usually do not go through a function pointer call.

+5
source share

All Articles