我想学习一些 Zig(也就是说,实际上这是我使用 Zig 的第三天),所以我决定在 Zig 中编写一个简单的基于 6502 的 8 位计算机模拟器,基于我现有的 C 项目。然而我遇到了一个问题,我不知道如何在 Zig 中至少以优雅的方式解决:
#define SOME_MACRO(a,b,OP) do { \
...
some_stuff = a OP b; \
...
} while (0)
... much later ...
SOME_MACRO(u1,u2,|); // OR operand version
...
SOME_MACRO(u1,u2,&); // AND operand version
... etc ...
显然,真正的代码比这复杂得多,但关键点是实际运算符(如
|
或&
)作为“C宏参数”传递。
据我目前对 Zig 的了解,我可以使用
inline
'd comptime
来实现与 C 宏类似的行为,但我不知道如何传递运算符作为参数。这也是我的好奇心,因为当然,通过一些像模式这样的元编程(也许使用 for
和 comptime
)我可以之前生成所需的 inline
函数,并且我可以按需使用其中一个函数稍后,而不是相同的“SOME_MACRO”。
是否有一些
@builtin
可以将运算符“名称”从调用参数或类似参数给定的常量直接推送到编译器?
Zig 没有办法将运算符传递给函数,相反,您必须使用 comptime 分支或传递回调函数
#define SOME_MACRO(a,b,OP) do { \
...
some_stuff = a OP b; \
...
} while (0)
具有回调函数:
fn SOME_MACRO(a: i32, b: i32, comptime OP: fn(a: i32, b: i32) i32) i32 {
const my_value = OP(a, b);
// or force inline with @call(.always_inline, OP, .{a, b});
return my_value;
}
fn OP_ADD(a: i32, b: i32) i32 {
return a + b;
}
const std = @import("std");
test "my macro" {
try std.testing.assert(SOME_MACRO(5, 6, OP_ADD) == 11);
}
带有comptime开关:
const Operator = enum {add, sub, mul, div, bitwise_or, bitwise_and};
fn SOME_MACRO(a: i32, b: i32, comptime OP: Operator) i32 {
return inline switch(OP) {
.add => a + b,
.sub => a - b,
.mul => a * b,
.div => @divTrunc(a, b),
.bitwise_or => a | b,
.bitwise_and => a & b,
};
}
const std = @import("std");
test "my macro" {
try std.testing.assert(SOME_MACRO(5, 6, .add) == 11);
}