I know that for structs, where I want guaranteed memory layout, I should use extern structs. However, I can’t use all Zig types in those. In some polymorphic use cases, it would be nice to have a base struct, that is always the first member of child structs and ensure that the base stays at memory offset 0 within the child struct. Is there a way to enforce this?
This feels like an XY problem. What are you hoping to achieve with this? I’m guessing that what you actually want is to use @fieldParentPtr, but without more info it’s hard to know.
You can enforce this using No, you can’t enforce this on plain extern struct. However,structs. I agree with the other comment, you probably do want @fieldParentPtr.
The author did mention that they could use extern struct, but pointed out that they would not be able to use all zig types.
Sorry about that, I misread.
For arbitrary fields using a struct, no. (to my knowledge)
Instead of using a struct you can manually get a piece of memory that has the right alignment and size and then using that pointer place your first field there, advancing the pointer by the size of the “field”, advancing the pointer forward by the alignment of the next field (std.mem.forwardAlign is zero if the alignment is right already) and so on.
Basically you calculate field offsets manually and emulate a struct, so you basically work with a comptime representation of a struct, instead of a real struct.
I don’t know of any other way that works with arbitrary fields.
You also could create some struct as a “template” for the layout, but then use types which work for the fields and write to the memory of the fields that don’t work via manual code instead of field assignment.
Thank you for the confirmation. Yes, this kind of approach is what I’ve been using. While working on zio I found many uses for having an “abstract” static-size struct that the core works with, but also extended version that depends on some comptime parameter, that needs special handling. In most cases, it’s the arguments or result value of a closure. I use @fieldParentPtr in the simpler cases, where I don’t care about the layout and this kind of manual pointer arithmetic where I care about the layout.