Skip to content

Instantly share code, notes, and snippets.

@DrkWithT
Last active March 9, 2025 00:00
Show Gist options
  • Save DrkWithT/b461b155ad5405ee33ca71187203c93d to your computer and use it in GitHub Desktop.
Save DrkWithT/b461b155ad5405ee33ca71187203c93d to your computer and use it in GitHub Desktop.
#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