Last active
March 9, 2025 00:00
-
-
Save DrkWithT/b461b155ad5405ee33ca71187203c93d to your computer and use it in GitHub Desktop.
This file contains hidden or 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 <stdlib.h> | |
#include <string.h> | |
#include <stdio.h> | |
typedef enum { | |
thing_flag, | |
thing_number, | |
thing_nil | |
} Thing; | |
typedef struct nil_t {} Nil; | |
typedef struct variant_t { | |
Thing tag; | |
union { | |
int num; | |
bool flag; | |
Nil foo; // placeholder | |
} data; | |
} BootlegVariant; | |
/// "generic" constructor | |
#define GEN_BOOTLEG_VARIANT_INIT(type)\ | |
void bootleg_variant_init_##type ( BootlegVariant* self, type arg ) {\ | |
_Generic((arg),\ | |
int: self->data.num = arg,\ | |
bool: self->data.flag = arg,\ | |
default:\ | |
self->data.foo = (Nil){}\ | |
);\ | |
_Generic((arg),\ | |
int: self->tag = thing_number,\ | |
bool: self->tag = thing_flag,\ | |
default:\ | |
self->tag = thing_nil\ | |
);\ | |
}\ | |
#define GEN_BOOTLEG_VARIANT_GET(type)\ | |
bool bootleg_variant_get_##type(const BootlegVariant* self, type* out_result) {\ | |
bool access_ok = true;\ | |
_Generic((*out_result),\ | |
int: access_ok = self->tag == thing_number,\ | |
bool: access_ok = self->tag == thing_flag,\ | |
default: access_ok = false\ | |
);\ | |
\ | |
if (access_ok) {\ | |
_Generic((*out_result),\ | |
int: *out_result = self->data.num,\ | |
bool: *out_result = self->data.flag,\ | |
default: 0\ | |
);\ | |
}\ | |
return access_ok;\ | |
}\ | |
/// fancy macro for calling "generic" functions | |
#define BOOTLEG_VARIANT_INIT_CALL(type, self_ptr, init_arg) bootleg_variant_init_##type(self_ptr, init_arg);\ | |
#define BOOTLEG_VARIANT_GET_CALL(type, self_ptr, out_arg) bootleg_variant_get_##type(self_ptr, out_arg)\ | |
/// generate "generic" functions for types | |
GEN_BOOTLEG_VARIANT_INIT(int) | |
GEN_BOOTLEG_VARIANT_INIT(bool) | |
GEN_BOOTLEG_VARIANT_GET(int) | |
GEN_BOOTLEG_VARIANT_GET(bool) | |
int main() { | |
BootlegVariant variant; | |
int answer = 0; | |
bool something = false; | |
BOOTLEG_VARIANT_INIT_CALL(int, &variant, 42) | |
if (BOOTLEG_VARIANT_GET_CALL(bool, &variant, &something)) { | |
puts("Yay!"); | |
} else { | |
puts("Nay!"); | |
} | |
if (BOOTLEG_VARIANT_GET_CALL(int, &variant, &answer)) { | |
puts("Yay!"); | |
} else { | |
puts("Nay!"); | |
} | |
printf("answer = %i\n", answer); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment