With statement expressions (gcc) we can go even farther.
Look at this fancy macro:
#define fifo_inst(T, name) \
\
T##FifoClass name = { \
.self = {0}, \
.put = ({void __fn__(T *src) {return T##FifoPut(&name.self, src);} __fn__;}), \
.get = ({void __fn__(T *dst) {return T##FifoGet(&name.self, dst);} __fn__;}), \
.len = ({ u32 __fn__(void) {return name.self.length;} __fn__;}), \
}
With this macro (kinda self-made C++ ) we can then use fifo (or whatever) like this:
int main(void) {
inst(fifo, Message, mq1);
// create an instance (on stack) of fifo named mq1
...
mq1.put(&message[k]);
...
mq1.get(&m);
It’s cool, yeah, but it’s a sort of a gimmick, while in Zig generics can be dealt with in more or less standard and clean way.