如何使用作为宏参数传递的运算符来“模拟”Zig 中 C 宏的行为?

问题描述 投票:0回答:1

我想学习一些 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
1个回答
0
投票

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.