gpt4 book ai didi

templates - 如何从宏创建参数化类型?

转载 作者:行者123 更新时间:2023-11-29 07:43:24 26 4
gpt4 key购买 nike

我有一个宏,它创建一个结构和一堆支持函数和特征实现。这个问题的有趣之处在于:

macro_rules! make_struct {
($name: ident) => {
struct $name;
}
}

这如您所料:

make_struct!(MyStruct);

但是,如果我想制作一个参数化类型,我就不走运了:

make_struct!(AnotherStruct<T: SomeTrait>);

test.rs:8:27: 8:28 error: no rules expected the token `<`
test.rs:8 make_struct!(AnotherStruct<T: SomeTrait>);

结构的名称是一个ident,所以我不能只在宏参数中更改它(例如更改为ty):

test.rs:3:16: 3:21 error: expected ident, found `MyStruct`
test.rs:3 struct $name;

那么我该如何编写这个宏才能同时处理这两者呢?或者我需要分开吗?在后一种情况下,宏是什么样的?

最佳答案

关键字struct 之后, 解析器需要一个标识标记树,它后面可能是 <和更多; ty 绝对不是它想要的(作为它为什么不起作用的一个例子,(Trait + Send + 'static) 是一个有效的 ty,但 struct (Trait + Send + 'static); 显然没有意义)。

要支持泛型,您需要制定更多规则。

macro_rules! make_struct {
($name:ident) => {
struct $name;
};
($name:ident<$($t:ident: $constraint:ident),+>) => {
struct $name<$($t: $constraint),+>;
}
}

正如您无疑观察到的那样,让它支持解析器在该位置接受的所有内容几乎是不可能的; macro_rules 没那么聪明。然而,有一个奇怪的技巧(静态代码分析器讨厌它!)它允许您获取一系列 token 树并将其视为正常的 struct。定义。它只使用了更多的 macro_rules 间接寻址:

macro_rules! item {
($item:item) => ($item);
}
macro_rules! make_struct {
($name:ident) => {
struct $name;
};
($name:ident<$($tt:tt)*) => {
item!(struct $name<$($tt)*;);
};
}

请注意,由于过度热心,ident目前不允许序列重复 ($(…)) 紧随其后,因此您将无法在 ident 之间放置一些标记树。和重复,例如$name:ident, $($tt:tt)* (产生 AnotherStruct, <T: SomeTrait> )或 $name:ident<$(tt:tt)* => struct $name<$($tt)*; . this 的值(value)降低了,因为你不能很容易地把它拆开来得到单独的泛型类型,你需要为插入 PhantomData 之类的事情做这件事。标记。

您可能会发现传递整个 struct 很有帮助元素;它传递为 item类型(就像 fnenumusetrait&c. 一样)。

关于templates - 如何从宏创建参数化类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30589067/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com