I can't search data in table with `functable[i].func()` because of comptime

I am having an issue with the following codes.

fn func01() void {
    print("func01\n", .{});
}
fn func02() void {
    print("func02\n", .{});
}
const FuncT = struct { no: u32, func: fn () void };
const functable = [_]FuncT{ FuncT{ .no = 1, .func = func01 }, FuncT{ .no = 2, .func = func02 } };

pub fn main() !void {
    var len = functable.len;
    for (0..len) |i| {
        functable[i].func();
    }
}

error code:

src/main.zig:18:19: error: values of type '[2]main.FuncT' must be comptime-known, but index value is runtime-known
        functable[i].func();

I don’t want to avoid using comptime as I can comply the codes as they are.

How to handle this issue?

You can use inline for

For loops can be inlined. This causes the loop to be unrolled, which allows the code to do some things which only work at compile time, such as use types as first class values. The capture value and iterator value of inlined for loops are compile-time known.

inline for (0..len) |i| {
    functable[i].func();
}
2 Likes

@sze answer is perfect for your needs, but I would like to highlight 3 points.

const std = @import("std");
const print = std.debug.print;

fn func01() void {
    print("func01\n", .{});
}
fn func02() void {
    print("func02\n", .{});
}
const FuncT = struct { no: u32, func: *const fn () void };
const functable = [_]FuncT{
    FuncT{ .no = 1, .func = func01 },
    FuncT{ .no = 2, .func = func02 },
};

pub fn main() !void {
    for (functable) |funct| {
        funct.func();
    }
}
  1. zig fmt formats horizontally if a comma is missing from the last element. I added a comma after the last FuncT in functable. If there is an extra comma after the last element zig fmt formats vertically.
  2. for statement accepts an array, you don’t need an index.
  3. Functions are for compile time only, function pointers can be used in runtime by adding a *const before fn.
2 Likes

@sze
Thanks for quick reply,
However, it didn’t work out as I tried inline before I posted.
error says

src/main.zig:15:17: error: unable to resolve comptime value
    inline for (0..len) |i| {
                ^---------

my version: 0.11.0

I’ am getting a much better error message:

test.zig:14:9: error: local variable is never mutated
    var len = functable.len;
        ^~~
test.zig:14:9: note: consider using 'const'

Changing to const it works.

const std = @import("std");
const print = std.debug.print;

fn func01() void {
    print("func01\n", .{});
}
fn func02() void {
    print("func02\n", .{});
}
const FuncT = struct { no: u32, func: fn () void };
const functable = [_]FuncT{ FuncT{ .no = 1, .func = func01 }, FuncT{ .no = 2, .func = func02 } };

pub fn main() !void {
    const len = functable.len;
    inline for (0..len) |i| {
        functable[i].func();
    }
}
3 Likes

Thanks a lot for leading me to resolve this.

Thanks as well for the following info. this resolves what I had been annoying.

  1. zig fmt formats horizontally if a comma is missing from the last element. I added a comma after the last FuncT in functable. If there is an extra comma after the last element zig fmt formats vertically.
2 Likes