This dilemma is why I called the generic functions which return types Type() in my emulator project.
E.g. you stamp out a specific Z80 CPU type like this:
const Z80 = z80.Type(.{ .pins = Z80_PINS, .bus = Bus });
IMHO this would just look silly:
const Z80 = z80.Z80(.{ .pins = Z80_PINS, .bus = Bus });
…the implementation file is z80.zig and has the Type() function in the root scope:
pub fn Type(comptime cfg: TypeConfig) type {
...
}
The only thing I don’t like is the deep nesting level that’s introduced by this approach, e.g.:
pub fn Type(comptime cfg: TypeConfig) type {
const Bus = cfg.bus;
return struct {
const Self = @This();
fn or8(self: *Self, val: u8) void {
self.r[A] |= val;
self.r[F] = szpFlags(self.r[A]);
}
…e.g. the actual code is 3 indentation levels to the right, haven’t found a good solution for this yet.