【问题标题】:Rust - Issue with macro rulesRust - 宏规则问题
【发布时间】:2021-04-29 15:53:38
【问题描述】:

我正在尝试构建以下宏,通过将类型转换为已实现的类型然后按预期执行操作,为各种类型实现 add-assign:

macro_rules! assign_for_value {
    ( $type_to_assign:ty, $cast_to_type:ty, $Add_or_Sub_Assign:ty, $add_or_sub_assign:ty, $add_or_sub:tt ) => {
        impl $Add_or_Sub_Assign<$type_to_assign> for ValueTerm {
            fn $add_or_sub_assign(&mut self, rhs: $type_to_assign) {
                *self $add_or_sub= rhs as $cast_to_type;
            }
        }
    };
}

assign_for_value!(i8, i64, AddAssign, add_assign, +);
assign_for_value!(i8, i64, SubAssign, sub_assign, -);

我想将它加倍作为所有操作类型的分配,尽管我收到以下错误:

error: expected `::`, found keyword `for`:

impl $Add_or_Sub_Assign<$type_to_assign> for ValueTerm {
                                         ^^^ expected `::`

这个错误很奇怪,对解释我做错了什么没有任何帮助。在stackoverflow上似乎找不到类似的东西所以我想问一下。非常感谢您对此提供任何帮助:)

【问题讨论】:

  • Rust 宏不连接文本,它们在 AST 级别上工作。一旦您请求将SubAssign 解析为ty,您就不能将&lt;T&gt; 粘贴到它上面以使其成为另一种类型。同样,$add_or_sub= 将不起作用,因为 += 是单个令牌,而不是 + 令牌与 = 令牌的串联,但您已强制 + 成为它自己的令牌。
  • 啊好的,我明白了,谢谢@mcarton 的信息 :)

标签: rust macros


【解决方案1】:

您可以将$Add_or_Sub_Assign$add_or_sub_assign 设为标识符 (:ident)。这样,它们可以分别用作类型和方法名称的 part(后者从来都不是类型)。您需要遵循 cmets 中提到的内容并将 += 设为单个令牌,而不是尝试拆分它。

macro_rules! assign_for_value {
    ( $type_to_assign:ty, $cast_to_type:ty, $Add_or_Sub_Assign:ident, $add_or_sub_assign:ident, $add_or_sub:tt ) => {
        impl $Add_or_Sub_Assign<$type_to_assign> for ValueTerm {
            fn $add_or_sub_assign(&mut self, rhs: $type_to_assign) {
                *self $add_or_sub rhs as $cast_to_type;
            }
        }
    };
}

assign_for_value!(i8, i64, AddAssign, add_assign, +=);
assign_for_value!(i8, i64, SubAssign, sub_assign, -=);

查看它在playground 上运行。

【讨论】:

  • 谢谢@kmdreko :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
相关资源
最近更新 更多