我正在尝试迭代
struct
的字段并根据字段的类型执行不同的操作:
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});
}
我的问题是:字段微分逻辑(
switch
)会发生在comptime
吗?,即实际的编译程序是否会类似于
result += 1;
result += 2;
--或者会更像
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,
}
我假设这些开关是不必要的,因为计算这些东西所需的一切在编译时都是已知的,但显然
switch
正在被评估,因为如果我声明 S.number
为 u32
,例如,执行会出现恐慌在unreachable
。
如果是这种情况,我该如何重写它以使其性能更高?
inline for
展开,每次迭代的代码都内联到生成的代码中进行编译。换句话说,这个
inline for (...) {
// some code ...
}
成为
// some code ...
// some code ...
如果是这种情况,我该如何重写它以使其性能更高?
这实际上对性能没有影响,因为在发布模式下编译器会优化这段代码。例如,我使用 godbolt 检查输出程序集是否有类似代码,编译器最终将其全部减少为:
example.main:
push rax
mov rdi, rsp
mov qword ptr [rsp], 3
call "log.scoped(.default).err__anon_3359"
pop rax
ret