4 ms·
C doesn't have any type-generic function declaration. So any viable solution had to be at least partially powered by a macro and resulting (one-directional) typ
by lifthrasiir 2y ago
C doesn't have any type-generic function declaration. So any viable solution had to be at least partially powered by a macro and resulting (one-directional) type inference.
- kevin_thibedeau 2y agoC11 does with _Generic but it is limited in ways that make min/max implementations flaky.
- pyth0 2y agoEven with _Generic you can't declare generic functions. You'd still need a macro call that uses _Generic to dispatch different implementations depending on the parameter types.
- dwattttt 2y agoGeneric dispatching all the type combinations (or warning or erroring) wouldn't be a problem in a project the scale of the Linux kernel. I'm unfamiliar with the incantations needed to try preserve constant expressions though, that might be too much for them.
- lifthrasiir 2y agoThe concrete problem that the kernel is facing is an exponential growth of macro expansion. Any current solution, safe or not in terms of re-evaluation, needs at least two copies of both arguments to be expanded [1], so expressions like `min(min(a, b), c)` will expand some arguments four times. The growth factor would be much larger than two if the definition wasn't carefully designed to avoid such cases. [1] `_Generic` also requires at least two because you need one copy to select the generic implementation and another to call it. C23 `typeof` (or the equivalent GNU extension) allows for a compact type tuple matching: inline static int max_int(int x, int y) { return x > y ? x : y; } inline static unsigned max_uint(unsigned x, unsigned y) { return x > y ? x : y; } /* ... */ #define MAX(a, b) (_Generic( \ (void (*)(typeof(a), typeof(b))) NULL, \ void (*)(int, int): max_int, \ void (*)(unsigned, unsigned): max_uint, \ /* ... */ \ default: max_type_error \ ) (a, b))
- kelnos 2y agoAlso _Generic is intended for a function that takes a single varying type. The kernel's min/max macros allow you to safely mix types.