Live data from Hacker News

Workarounds for C11 _Generic()

chiark.greenend.org.uk

1–10 of 58 posts

Re: Workarounds for C11 _Generic()

#2
According to this the "big bug" is that... _Generic works mostly like a macro and expands code that the compiler sees. That seems like a little weak, macros have been doing this forever via a mere extra level of indirection.

So sure, "(x)->length" might not be valid syntax in all configurations the compiler might see. But "LENGTH(x)" is, e.g.:

   #if X_MIGHT_BE_MYSTRINGBUFFER
   #define LENGTH(x) ((x)->length)
   #else
   #define LENGTH(x) 0 /* anything that converts to the output type will do */
   #endif
This is a routine pattern seen everywhere in C. The Linux kernel is filled with it, e.g. field accessors or arch-specific functions that are stubbed out when not needed, etc...

Is this as clean as a full-on generic typesystem? No. But it's C, it shows a weirdness that you have to handle manually, and you do it the same way we've been doing it in C for decades. Not a new problem, doesn't need a new solution. It's C!

Re: Workarounds for C11 _Generic()

#3
It's amazing how much power _Generic, typeof, typeof_unqual, auto and empty brace initializers can give to the compile time of C (that we already enjoy in C++ through templates, constexpr, auto and friends). Now, if only we had a way to write generic code in a reliable way...

Re: Workarounds for C11 _Generic()

#4
post #2

According to this the "big bug" is that... _Generic works mostly like a macro and expands code that the compiler sees. That seems like a little weak, macros have been doing this forever via a mere extra level of indirection. So sure, "(x)->length" might not be valid syntax in all configurations the compiler might see. But "LENGTH(x)" is, e.g.: #if X_MIGHT_BE_MYSTRINGBUFFER #define LENGTH(x) ((x)->length) #else #defin…

Macros and #ifdef do not solve the problems that _Generic is used for. _Generic is for static polymorphism, not for target or build configuration.

Re: Workarounds for C11 _Generic()

#6

Will this work? define string_length(x) _Generic(x, \ const char * : strlen((const char*)(const void*)x), \ struct MyStringBuffer * : ((const MyStringBuffer*)(const void*)x)->length)

Heh, this was my first thought as well, and it does indeed compile and work (with GCC 12.2, anyway).

Re: Workarounds for C11 _Generic()

#7
post #2

According to this the "big bug" is that... _Generic works mostly like a macro and expands code that the compiler sees. That seems like a little weak, macros have been doing this forever via a mere extra level of indirection. So sure, "(x)->length" might not be valid syntax in all configurations the compiler might see. But "LENGTH(x)" is, e.g.: #if X_MIGHT_BE_MYSTRINGBUFFER #define LENGTH(x) ((x)->length) #else #defin…

I think you've misunderstood the purpose of _Generic.

Your #if statement will select exactly one implementation for every single site of the use of LENGTH() in the codebase, depending on the value of X_MIGHT_BE_MYSTRINGBUFFER at compile-time.

_Generic() allows you to have both implementations available, and different implementations can be selected at the call site depending on the type of the argument passed.

Post reply on HN