Provides a way to choose one of several expressions at compile time, based on a type of a controlling expression
Contents |
_Generic(controlling-expression,association-list) | (since C11) | ||||||||
whereassociation-list is a comma-separated list of associations, each of which has the syntax
type-name:expression | |||||||||
default:expression | |||||||||
where
| type-name | - | any completeobject type that isn't variably-modified (that is, not VLA or pointer to VLA). |
| controlling-expression | - | any expression (except for thecomma operator) whose type must be compatible with one of thetype-names if thedefault association is not used |
| expression | - | any expression (except for thecomma operator) of any type and value category |
No twotype-names in theassociation-list may specifycompatible types. There may be only one association that uses the keyworddefault. Ifdefault is not used and none of thetype-names are compatible with the type of the controlling expression, the program will not compile.
First, the type ofcontrolling-expression undergoeslvalue conversions. The conversion is performed in type domain only: it discards the top-level cvr-qualifiers and atomicity and applies array-to-pointer/function-to-pointer transformations to the type of the controlling expression, without initiating any side-effects or calculating any values.
The type after conversion is compared withtype-names from the list of associations.
If the type iscompatible with thetype-name of one of the associations, then the type, value, andvalue category of the generic selection are the type, value, and value category of theexpression that appears after the colon for thattype-name.
If none of thetype-names are compatible with the type of thecontrolling-expression, and thedefault association is provided, then the type, value, and value category of the generic selection are the type, value, and value category of the expression after thedefault : label.
Thecontrolling-expression and theexpressions of the selections that are not chosen are never evaluated.
Because of the lvalue conversions,"abc" matcheschar* and notchar[4] and(intconst){0} matchesint, and notconstint.
Allvalue categories, including function designators and void expressions, are allowed asexpressions in a generic selection, and if selected, the generic selection itself has the same value category.
Thetype-generic math macros from<tgmath.h>, introduced in C99, were implemented in compiler-specific manner. Generic selections, introduced in C11, gave the programmers the ability to write similar type-dependent code.
Generic selection is similar to overloading in C++ (where one of several functions is chosen at compile time based on the types of the arguments), except that it makes the selection between arbitrary expressions.
#include <math.h>#include <stdio.h> // Possible implementation of the tgmath.h macro cbrt#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) int main(void){double x=8.0;constfloat y=3.375;printf("cbrt(8.0) = %f\n",cbrt(x));// selects the default cbrtprintf("cbrtf(3.375) = %f\n",cbrt(y));// converts const float to float,// then selects cbrtf}
Output:
cbrt(8.0) = 2.000000cbrtf(3.375) = 1.500000
The following behavior-changing defect reports were applied retroactively to previously published C standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| DR 481 | C11 | it was underspecified if the controlling expression undergoes lvalue conversions | it undergoes |
C++ documentation forTemplates |