After I made the post yesterday I went and added the âadditional fieldâ to see how it looks like.
So in my struct I added this field:
data: ?*anyopaque = null,
/// to be called only during deinit()
free_data: ?*const fn (*const Self) void = null,
called in deinit() like so (there is an allocator field also, btw)
pub fn deinit(
self: *const Self,
) void {
if (self.free_data) |func| func(self);
// other things
}
and it is assigned to during construction from the same vtable that creates the data
// different `self` here.
if (self.vtable.create_data) |func| {
p.data = try func(&p);
p.free_data = self.vtable.free_data;
}
and then creating the vtable functions accordingly. All in all it was
10 files changed, 88 insertions(+), 5 deletions(-)
It works fine, I guess. I am just not entirely happy about the idea of an additional field that amounts to a private method.
I am not comfortable enough with pointer tagging and I dont really want to do architecture specific stuff anyway, as this is a library.
The other idea is as yall indicated just change the type of data to something like
struct {
kind: enum {
// insert types here
},
data: *anyopaque,
}
or now that I am typing it probably better as a union(enum) .. more type safe .. which is also fine. The only slight problem with that is that the definition and usage of data isnt confined to one file per type any more. Maybe I will try that next and see how it looks.
Thanks for the ideas everyone.