Match
Description
Open a match over x. The scrutinee is copied by value (so rvalues / function returns work); each When arm binds it (or, for a variant, its payload) to a name you give. Pair with When arms and an optional trailing Otherwise. Arms are mutually exclusive; the block runs at most one of them.
For a static match the selector is a _Generic constant, so exactly one arm is live per instantiation and the construct folds to it; the others are dead but must still compile against the value’s static type. This makes the static form meaningful inside generic/macro code, and free everywhere else.
Usage example (from documentation)
Match(value) {
When(int, n) WriteFmtLn("int {}", n);
When(double, d) WriteFmtLn("double {}", d);
Otherwise WriteFmtLn("other");
}Success
Runs the body of the single matching arm (or Otherwise if none), with that arm’s named binding in scope. Block exits after one arm.
Failure
If no When matches and there is no Otherwise, the match is non-exhaustive and aborts via LOG_FATAL – it never silently falls through. A When body that misuses its binding’s type is a compile error (every arm is type-checked).
Usage example (Cross-references)
Usage examples (Cross-references)
- In
TypeMatch.h:79:
#define Match(x) \
for (bool MisraMatched = false, UNPL(tm_once) = true; UNPL(tm_once); UNPL(tm_once) = false, \
ASSERT_OR_FATAL(MisraMatched, "Match: no arm matched and no Otherwise (non-exhaustive)")) \
for (TYPE_OF(x) MisraSubject = (x), *UNPL(tm_loop) = &MisraSubject; UNPL(tm_loop); UNPL(tm_loop) = NULL)- In
Variant.c:20:
Number n = Number_from_int(42);
bool hit = false;
Match(n) {
When(Number, int, v) hit = (v == 42);
When(Number, double, v) hit = false;- In
Variant.c:27:
Number m = Number_from_double(2.5);
bool hd = false;
Match(m) {
When(Number, int, v) hd = false;
When(Number, double, v) hd = (v == 2.5);- In
Variant.c:39:
int ai = 0;
double bd = 0.0;
Match(a) {
When(Number, int, n) ai = n * 2; // n : int
When(Number, double, r) bd = r;- In
Variant.c:43:
When(Number, double, r) bd = r;
}
Match(b) {
When(Number, int, n) ai = n;
When(Number, double, r) bd = r * 2.0; // r : double
- In
Variant.c:52:
// value in, value out -- no pointers
static Number twice(Number n) {
Match(n) {
When(Number, int, v) return Number_from_int(v * 2);
When(Number, double, v) return Number_from_double(v * 2.0);- In
Variant.c:62:
Number r = twice(Number_from_int(21));
bool ok = false;
Match(r) {
When(Number, int, v) ok = (v == 42);
When(Number, double, v) ok = false;- In
Variant.c:72:
bool ok = false;
// Match directly on a function-return rvalue.
Match(twice(Number_from_double(1.5))) {
When(Number, int, v) ok = false;
When(Number, double, v) ok = (v == 3.0);- In
Variant.c:83:
Cell c = Cell_from_char('Z');
bool ok = false;
Match(c) {
When(Cell, int, v) ok = false;
When(Cell, char, v) ok = (v == 'Z');- In
Variant.c:95:
bool ok = true;
for (int k = 0; k < 3; k++) {
Match(vals[k]) {
When(Tri, int, v) ok = ok && (v == 7), seen |= 1;
When(Tri, float, v) ok = ok && (v == 1.5f), seen |= 2;- In
Variant.c:107:
Number n = Number_from_int(7);
int count = 0;
Match(n) {
When(Number, int, v) count++;
When(Number, double, v) count++;- In
Variant.c:118:
bool deadend_variant_nonexhaustive(void) {
Number n = Number_from_double(9.0); // holds double, only int handled, no Otherwise
Match(n) {
When(Number, int, v)(void) v;
}- In
TypeMatch.c:21:
int tag = -1;
Match(i) {
When(int, v) tag = 0;
When(double, v) tag = 1;- In
TypeMatch.c:28:
bool ok = tag == 0;
Match(d) {
When(int, v) tag = 0;
When(double, v) tag = 1;- In
TypeMatch.c:36:
// Unlisted type falls to Otherwise.
Match(p) {
When(int, v) tag = 0;
When(double, v) tag = 1;- In
TypeMatch.c:50:
int ri = 0;
double rd = 0.0;
Match(i) {
When(int, n) ri = n * 2;
When(double, x) rd = x;- In
TypeMatch.c:54:
When(double, x) rd = x;
}
Match(d) {
When(int, n) ri = n;
When(double, x) rd = x * 2.0;- In
TypeMatch.c:65:
bool hit = false;
// Scrutinee is an rvalue; copied by value, then bound to `n`.
Match(i + 1) {
When(int, n) hit = (n == 5);
When(double, x) hit = false;- In
TypeMatch.c:75:
int i = 7;
int count = 0;
Match(i) {
When(int, v) count++;
When(double, v) count++;- In
TypeMatch.c:86:
Position2D p = {1.0f, 2.0f};
bool hit = false;
Match(p) {
When(int, v) hit = false;
When(double, v) hit = false;- In
TypeMatch.c:99:
int oi = 0;
double id = 0.0;
Match(i) {
When(int, outer) {
Match(d) {- In
TypeMatch.c:101:
Match(i) {
When(int, outer) {
Match(d) {
When(int, x) id = -1.0;
When(double, x) id = x; // inner bind : double
- In
TypeMatch.c:121:
bool deadend_match_nonexhaustive(void) {
Position2D p = {1.0f, 2.0f};
Match(p) {
When(int, v)(void) v; // never matches Position2D, and there is no Otherwise
}