# How to iterate over struct declarations?

**URL:** <https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782>\
**Category:** Help\
**Tags:** comptime\
**Created:** [January 8, 2024, 12:34pm UTC](https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782 "2024-01-08T12:34:26Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![zigitta-the-famous](https://ziggit.dev/letter_avatar_proxy/v4/letter/z/9d8465/32.png) [@zigitta-the-famous](https://ziggit.dev/u/zigitta-the-famous)\
**Post date:** [January 8, 2024, 12:34pm UTC](https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782/1 "2024-01-08T12:34:26Z")

</div>

Hai, ive been fiddling around lately with zig and have encountered some perplexing behaviour. My intention was to iterate through the functions of K, but I could not do that. Is that at all possible?

```zig
const std = @import("std");
// just a plain struct
const K = struct {
    field:u1 = 0,
    fn k(self: *const @This()) void { std.debug.print("YO {}", .{self.field}); }
};
pub fn main() void {
    std.debug.print("{}", .{@hasDecl(K, "k")}); // this shows true
    // std.fmt.comptimePrint("{any}", .{@typeInfo(K).Struct.decls}); // (1) this doesn't work (but should?)
    // @compileLog(@typeInfo(K).Struct.decls); // (2) this shows 0 items, but there should be 1, right?
}

```

---

<div class="post-metadata">

**Author:** ![IntegratedQuantum](https://ziggit.dev/user_avatar/ziggit.dev/integratedquantum/32/782_2.png) [@IntegratedQuantum](https://ziggit.dev/u/IntegratedQuantum)\
**Post date:** [January 8, 2024, 12:47pm UTC](https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782/2 "2024-01-08T12:47:58Z")

</div>

`@typeInfo` is only showing public declaration. [This is intended behavior](https://github.com/ziglang/zig/issues/10731#issuecomment-1502056337)  
`@hasDecl` checks if the declaration exists and is accessible from the current scope.

If you want to iterate through functions of `K` it seems like your only option is to make the relevant functions public, or iterate through them in another way(for example if you have numbered names you can easily iterate through them with `@hasDecl`).

> [@zigitta-the-famous](#):
>
> `// std.fmt.comptimePrint("{any}", .{@typeInfo(K).Struct.decls}); // (1) this doesn't work (but should?)`

`fmt.comptimePrint` is intended to print to a comptime string. The naming might be a bit confusing, but this is in line with `fmt.bufPrint` printing to a supplied buffer and `fmt.allocPrint` printing to an allocated buffer.  
`@compileLog` is the only intended way to print stuff at compile time.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [January 8, 2024, 5:43pm UTC](https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782/3 "2024-01-08T17:43:04Z")

</div>

@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:

```zig
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.

---

<div class="post-metadata">

**Author:** ![AndrewCodeDev](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/278dde/32.png) [@AndrewCodeDev](https://ziggit.dev/u/AndrewCodeDev)\
**Post date:** [March 26, 2024, 11:00pm UTC](https://ziggit.dev/t/how-to-iterate-over-struct-declarations/2782/4 "2024-03-26T23:00:44Z")

</div>

Quick update here - `@field` works for declarations too: [Documentation - The Zig Programming Language](https://ziglang.org/documentation/master/#toc-field)
