I'm trying a thing that iterates over the fields of a struct and does a different action according to the type of the field:
const std = @import("std");
const S = struct {
letter: u8,
number: u64,
};
pub fn main() void {
var result: i64 = 0;
var s = S{ .letter = 'a', .number = 77 };
inline for ([_][]const u8{ "letter", "number" }) |fname| {
var v = @field(s, fname);
switch (@TypeOf(v)) {
u8 => result += 1,
u64 => result += 2,
else => unreachable,
}
}
std.debug.print("result={}\n", .{result});
}
My question is: will the field differentiation logic (the switch) happen at comptime?, i.e. will the actual compile program be similar to
result += 1;
result += 2;
-- or will it be more like
const type1 = u8;
switch (type1) {
u8 => result += 1,
u64 => result += 2,
else => unreachable,
}
const type2 = u64;
switch (type2) {
u8 => result += 1,
u64 => result += 2,
else => unreachable,
}
I was assuming these switches were unnecessary since everything required to compute these things are known at compile time, but apparently the switch is being evaluated, because if I declare S.number to be u32, for example, the execution panics at the unreachable.
If that is the case, how can I rewrite this to make it more performant?
inline foris unrolled and the code for each iteration is inlined into the resulting code for compilation. In other words, thisbecomes
This doesn't really have affect on performance, because in release mode the compiler will optimize this code. For example, I've used godbolt to check the output assembly for a similar code and the compiler ended up reducing it all down to: