How to iterate over struct declarations?

@IntegratedQuantum is correct about the decl/field visibility issue (I believe this had to do with the @import functionality… can’t find the git issue anymore) - here’s a way to turn declarations into comptime fields so you can iterate over them:

const std = @import("std");

fn fooImpl(x: usize) usize { return x + 1; }
fn barImpl(x: usize) usize { return x - 1; }

const DeclsStruct = struct {
    foo: @TypeOf(fooImpl) = fooImpl,
    bar: @TypeOf(barImpl) = barImpl,
    baz: comptime_int = 42,
};

fn countFunctionFields(comptime T: type) usize {
    comptime var count = 0;
    for (@typeInfo(T).Struct.fields) |field| {
        if (@typeInfo(field.type) == .Fn) {
            count += 1;
        }
    }
    return count;
}

const Composite = struct {
    decls: DeclsStruct = .{},
    // other stuff...
};

pub fn main() !void {

    const func_fields = comptime countFunctionFields(DeclsStruct);

    std.debug.print("\nNumber of function fields: {}\n", .{ func_fields });
    
    const comp = Composite{ };
    std.debug.print("\n{}\n", .{ comp.decls.foo(42) });
    std.debug.print("\n{}\n", .{ comp.decls.bar(42) });
    std.debug.print("\n{}\n", .{ comp.decls.baz });
}

Now that we have wrapped foo and bar with the DeclsStruct, you’ll notice that the count is now two for detecting members that are functions (please note, these are not function pointers - they are compile time objects). Infact, all declarations can be converted to comptime fields.

If it’s important for you to be able to iterate over decls, you can use this path to manufacture an object that enables you to do this. It’s not directly native, but it’s not far off either.

@zigitta-the-famous, also - welcome to the forum. I’m going to edit the title title of this thread so it’s easier to search for future users.

1 Like