I personally use an different form similar to X macro, but I can add any number of parameter without the need of changing everything. And the way I use them is a tiny bit more flexible.
Here is a short (modified for the example) portion of code for an interpreter I wrote in C,
My ways of making extensible enum (enum with more data attach to it) look like:
```c
#define category_int 'i'
#define category_float 'f'
// defining the enum named bi (build in) : (c type, type category)
#define i32_bi (int32_t , category_int)
#define i64_bi (int64_t , category_int)
#define f32_bi (float, category_float)
#define f64_bi (double, category_float)
// each member of the enum should have the same number of value
// you can do add more data attach to it like: (int32_t , category_int, "INT", 1)
```
Getting the info you need about an bi :
```c
#define get_1(a, b) a
#define get_2(a, b) b
#define bi_type(bi) get_1 bi
#define bi_category(bi) get_2 bi
```
so things like `bi_category(f64_bi)` -> `category_float` === `'f'` work
Mapping enum to stuff (function, macro...) :
```c
//build_in = (integer_type) Union (float_type)
// map the macro on all integer type inside bi :
#define map_on_bi_integer(macro)\
macro(i32_bi)\
macro(i64_bi)
#define map_on_bi_float(macro)\
macro(f32_bi)\
macro(f64_bi)
#define map_on_bi(macro)\
map_on_bi_integer(macro)\
map_on_bi_float(macro)
```
And then map it to whatever ! You can generate enum, switch case, custom function body and definition...
```c
// glue without evaluating the macro a and b
#define glue_instant(a,b) a ## b
// eval the macro FIRST, and then glue the result (other wise you will glue the unevaluated macro
#define glue(a,b) glue_instant(a, b)
enum bi_enum
{
// note : the ## glue macro don't directly work here, you need
Thank for this post, I just discover the blog !
I personally use an different form similar to X macro, but I can add any number of parameter without the need of changing everything. And the way I use them is a tiny bit more flexible.
Here is a short (modified for the example) portion of code for an interpreter I wrote in C,
My ways of making extensible enum (enum with more data attach to it) look like:
```c
#define category_int 'i'
#define category_float 'f'
// defining the enum named bi (build in) : (c type, type category)
#define i32_bi (int32_t , category_int)
#define i64_bi (int64_t , category_int)
#define f32_bi (float, category_float)
#define f64_bi (double, category_float)
// each member of the enum should have the same number of value
// you can do add more data attach to it like: (int32_t , category_int, "INT", 1)
```
Getting the info you need about an bi :
```c
#define get_1(a, b) a
#define get_2(a, b) b
#define bi_type(bi) get_1 bi
#define bi_category(bi) get_2 bi
```
so things like `bi_category(f64_bi)` -> `category_float` === `'f'` work
Mapping enum to stuff (function, macro...) :
```c
//build_in = (integer_type) Union (float_type)
// map the macro on all integer type inside bi :
#define map_on_bi_integer(macro)\
macro(i32_bi)\
macro(i64_bi)
#define map_on_bi_float(macro)\
macro(f32_bi)\
macro(f64_bi)
#define map_on_bi(macro)\
map_on_bi_integer(macro)\
map_on_bi_float(macro)
```
And then map it to whatever ! You can generate enum, switch case, custom function body and definition...
```c
// glue without evaluating the macro a and b
#define glue_instant(a,b) a ## b
// eval the macro FIRST, and then glue the result (other wise you will glue the unevaluated macro
#define glue(a,b) glue_instant(a, b)
enum bi_enum
{
// note : the ## glue macro don't directly work here, you need
#define declare_bi_enum_member(bi) glue(enum_,bi_type(bi)),
map_on_bi(declare_bi_enum_member)
/*
expend to :
enum_i32_bi, enum_i64_bi, enum_f32_bi, enum_f64_bi,
*/
#undef declare_bi_enum_member
}
Here is a switch case exemple :
```c
bool get_category(bi_enum b)
{
switch(b)
{
#define handle_case(bi)\
case glue(enum_, bi): return bi_category(bi); break;
/*break is not really helpful but anyways*/
map_on_bi(handle_case)
default: TODO; break; // (some macro to crash and tell the case was not implemented)
}
}
// or you can define a global array of bool if you want
```
the `map_on...` macro are great to map stuff, especially because you can create different family like :
```c
bool display(bi_enum b)
{
switch(b)
{
#define handle_int(bi)\
case glue(enum_, bi): printf("some integer!"); break;
#define handle_float(bi)\
case glue(enum_, bi): printf("some float!"); break;
/*break is not really helpful but anyways*/
map_on_bi_integer(handle_int)
map_on_bi_float(handle_float)
default: TODO; break;
}
}
```
I generally I put the enum number inside the define (`#define i32_bi (int32_t , category_int, 1)`), and add :
```
#define get_3(a, b, c) c
#define bi_id(bi) get_3 bi
```
so I don't declare an enum and the macro are a tiny bit easier to write.
But you can do it without it like in this example if you want.
(Fun fact, I'm a 21 years student in CS)