A type-generic interface gives one operation name to behavior that depends on an argument’s type. For example, <tgmath.h> provides a type-generic cos macro instead of requiring callers to choose among cos, cosf, and cosl for double, float, and long double. Each such macro represents a finite set of functions. section 18.1.7
#define fabs(X) \ _Generic((X), \ float: fabsf, \ long double: fabsl, \ default: fabs)(X)
A _Generic expression selects a function according to the type of X; the selected function is then called with X. section 18.2
_Generic is a C11 expression, not itself a macro facility. Its controlling expression guides a choice among type associations and an optional default. Placing that choice in a function-like macro supplies a single call interface: in the fabs example, float selects fabsf, long double selects fabsl, and other arithmetic types fall through to fabs. section 18.2
TAKEAWAY: choose the mechanism—and check its limits—before treating one name as a universal operation.
- Arithmetic expressions in macros can use the usual promotions and conversions to work across types. Macros can also generate declarations or statement-like operations, but statement macros need care with argument evaluation and syntax. section 18.1.3
- _Generic selects from specified types. Interfaces involving combinations of types require more cases and attention to conversions; a minimum-of-two-values macro can use the sum of its arguments to select among floating-point functions. section 18.0 section 18.2
- Type inference with C23 auto, typeof, and typeof_unqual offers another way to maintain type consistency without enumerating every case. section 18.0 section 18.5
#include "c23-fallback.h" char const unmut_str[] = "haystack"; char mut_str[] = "hoystack"; char const needle[] = "stack"; char* mut_pos0 = strstr(unmut_str, needle); // error char const* unmut_pos0 = strstr(unmut_str, needle); // ok char* mut_pos1 = strstr(mut_str, needle); // ok char const* unmut_pos1 = strstr(mut_str, needle); // ok char* mut_pos2 = (strstr)(unmut_str, needle); // possible invalid access
The C23 strstr macro interface preserves a const-qualified argument’s qualification in the returned pointer. Parenthesizing the name calls the function interface instead, bypassing that protection. section 18.1.7
Type-generic interfaces extend beyond math: C23 adds qualification-preserving interfaces for selected string-search and bsearch functions, while <stdatomic.h> has interfaces for atomic types. Their implementations need not use the same selection technique. section 18.1.7

