# How to create functions/declarations for struct/union/enum at compile time?

**URL:** <https://ziggit.dev/t/how-to-create-functions-declarations-for-struct-union-enum-at-compile-time/5083>\
**Category:** Help\
**Tags:** language\
**Created:** [July 11, 2024, 5:38am UTC](https://ziggit.dev/t/how-to-create-functions-declarations-for-struct-union-enum-at-compile-time/5083 "2024-07-11T05:38:04Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![felpafel](https://ziggit.dev/letter_avatar_proxy/v4/letter/f/ecae2f/32.png) [@felpafel](https://ziggit.dev/u/felpafel)\
**Post date:** [July 11, 2024, 5:38am UTC](https://ziggit.dev/t/how-to-create-functions-declarations-for-struct-union-enum-at-compile-time/5083/1 "2024-07-11T05:38:04Z")

</div>

Hello everyone, I’m having some trouble figuring out how to create (if possible) a declaration for a struct/union/enum using `comptime` and metaprogramming. In other words:  
How to, programmatically, create a function/declaration that translates to:

```zig
const Foo = struct {
  pub fn bar() void {}
}

```

I’ve found [this post](https://ziggit.dev/t/programmatically-adding-a-const-decl-to-a-struct-type-at-comptime/3959/10) asking a similar (maybe the same) question, that suggests wrapping the struct/union/enum in another struct/union/enum. Is this the only solution?

My use case is the following:

I’m initializing a `enum` (`Tokens`) and a `StaticStringMap` (`TokensMap`) using a const variable (`_tokens`), so I can add/remove fields from one place and have the `enum` and the `StringMap` automatically updated.

```zig
const _tokens = [_][2][:0]const u8{
    // (K,V) pairs
    .{ "+", "plus" },
    .{ "-", "minus" },
};

const Tokens = b: {
    var enum_fields: [_tokens.len]std.builtin.Type.EnumField = undefined;
    var i: u8 = 0;
    for (&enum_fields, _tokens) |*enum_field, token| {
        enum_field.* = .{ .name = token[1], .value = i };
        i += 1;
    }
    break :b @Type(.{ .Enum = .{
        .decls = &.{},
        .fields = &enum_fields,
        .tag_type = u8,
        .is_exhaustive = false,
    } });
};

const TokensMap = b: {
    var map_kvs: [_tokens.len]struct { [:0]const u8, Tokens } = undefined;
    var i: u8 = 0;
    for (&map_kvs, _tokens) |*map_kv, token| {
        map_kv.* = .{ token[0], @enumFromInt(i) };
        i += 1;
    }
    break :b std.StaticStringMap(Tokens).initComptime(map_kvs);
};

```

The code behaves as intended, but I want `_tokens` and `TokensMap` only present in the `enum` (`Tokens`) scope, and expose functions from the `enum` itself, so instead of calling `TokensMap.has()` I can call `Tokens.has()`, for example.

---

<div class="post-metadata">

**Author:** ![ktz\_alias](https://ziggit.dev/user_avatar/ziggit.dev/ktz_alias/32/1202_2.png) [@ktz\_alias](https://ziggit.dev/u/ktz_alias)\
**Post date:** [July 11, 2024, 6:34am UTC](https://ziggit.dev/t/how-to-create-functions-declarations-for-struct-union-enum-at-compile-time/5083/2 "2024-07-11T06:34:05Z")

</div>

Probably, It seems that it cannot append function declarations dynamically.

As the alternative idea, you can implemented as file scope unit.

For example:

```zig
// Tokens.zig

const std = @import("std");

const _tokens = [_][2][:0]const u8{
    // (K,V) pairs
    .{ "+", "plus" },
    .{ "-", "minus" },
};

pub const Tag = b: {
    var enum_fields: [_tokens.len]std.builtin.Type.EnumField = undefined;
    var i: u8 = 0;
    for (&enum_fields, _tokens) |*enum_field, token| {
        enum_field.* = .{ .name = token[1], .value = i };
        i += 1;
    }
    break :b @Type(.{ .Enum = .{
        .decls = &.{},
        .fields = &enum_fields,
        .tag_type = u8,
        .is_exhaustive = false,
    } });
};

const TokensMap = b: {
    var map_kvs: [_tokens.len]struct { [:0]const u8, Tag } = undefined;
    var i: u8 = 0;
    for (&map_kvs, _tokens) |*map_kv, token| {
        map_kv.* = .{ token[0], @enumFromInt(i) };
        i += 1;
    }
    break :b std.StaticStringMap(Tag).initComptime(map_kvs);
};

pub fn has(op: []const u8) bool {
    return TokensMap.has(op);
}

```

In caller:

```zig
const std = @import("std");
const Tokens = @import("./Tokens.zig");

pub fn main() !void {
    std.debug.print("`+`: {}\n", .{Tokens.has("+")});
    std.debug.print("`/`: {}\n", .{Tokens.has("/")});
}

```

Result:

```zig
`+`: true
`/`: false

```

---

<div class="post-metadata">

**Author:** ![felpafel](https://ziggit.dev/letter_avatar_proxy/v4/letter/f/ecae2f/32.png) [@felpafel](https://ziggit.dev/u/felpafel)\
**Post date:** [July 11, 2024, 7:26am UTC](https://ziggit.dev/t/how-to-create-functions-declarations-for-struct-union-enum-at-compile-time/5083/3 "2024-07-11T07:26:41Z")

</div>

Thanks for your response, it’s a good solution, and since _all Zig source files are structs_ the solution is “to wrap into another struct”, haha.

After making the post I found more information related to the current state of declarations and `@Type()`, apparently the main ones are [#6709](https://github.com/ziglang/zig/issues/6709) and [#10710](https://github.com/ziglang/zig/issues/10710).

To end it all, I learned a new verb.  
**Reify** : To make (something abstract) more concrete or real, as in “error: reified structs must have no decls”.
