-
-
Save adragomir/fa49e4eeba47113babfc3630f4c7d493 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <stddef.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#define tag(x) ((ptrdiff_t)&Tag##x) | |
#define is(x, T) ((x)->tag == tag(T)) | |
#define as(x, T) ((struct T *)variant_cast((void *)(x), tag(T))) | |
static inline void* | |
variant_cast(void * variant_ptr, ptrdiff_t desired_tag) { | |
ptrdiff_t * variant_tag = (ptrdiff_t *)variant_ptr; | |
assert(*variant_tag == desired_tag); | |
return (void *)((char *)variant_ptr + sizeof(ptrdiff_t)); | |
} | |
#include <errno.h> | |
struct Error { | |
int id; | |
} TagError; | |
struct Value { | |
float z; | |
float w; | |
} TagValue; | |
struct Result { | |
ptrdiff_t tag; | |
union { | |
struct Error _; | |
struct Value __; | |
}; | |
}; | |
struct Result | |
function_with_possible_error(int n) | |
{ | |
struct Result res; | |
if (n < 0) { | |
res.tag = tag(Error); | |
struct Error *e = as(&res, Error); | |
e->id = ENOMEM; | |
return res; | |
} | |
res.tag = tag(Value); | |
struct Value *v = as(&res, Value); | |
v->w = 5.0f; | |
v->z = 2.0f; | |
return res; | |
} | |
struct Result | |
function_taking_some(struct Result r, float n) | |
{ | |
struct Result res = r; | |
if (is(&res,Error)) | |
return r; | |
if (n < 0) { | |
res.tag = tag(Error); | |
struct Error *e = as(&res, Error); | |
e->id = EINVAL; | |
return res; | |
} | |
struct Value *v = as(&res, Value); | |
v->w += n; | |
return res; | |
} | |
int main() { | |
struct Result res = {}; | |
res = function_with_possible_error(5); | |
res = function_taking_some(res, 2.0f); | |
if (is(&res, Error)) { | |
struct Error *err = as(&res, Error); | |
printf("%d\n", err->id); | |
} else if (is(&res, Value)) { | |
struct Value *v = as(&res, Value); | |
printf("%.2f, %.2f\n", v->z, v->w); | |
} return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment