如何有条件地更改Rust宏的一小部分? [英] How to conditionally change a small part of a Rust macro?

查看:47
本文介绍了如何有条件地更改Rust宏的一小部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个具有 foo 功能的板条箱.这个箱子有一个宏 bar!,它根据是否设置了 foo 来做细微的事情.

I am building a crate which has the feature foo. This crate has a macro bar! that does subtly different things based on whether foo is set.

我可以复制整个宏:

#[cfg(feature = "foo")]
macro_rules! bar {
    // Lots of rules...

    ( A ) => {
        B
    }
}

#[cfg(not(feature = "foo"))]
macro_rules! bar {
    // Lots of rules...

    ( A ) => {
        C
    }
}

这是很多容易出错的重复.两种无效的方法:

That's a lot of error-prone duplication. Two approaches that don't work:

  • 我们无法在宏内移动 cfg ,因为它会在板条箱用户的范围内扩展,而该范围未正确设置功能 foo .

  • We can't move the cfg inside the macro, because then it will expand in the crate user's scope, which does not have feature foo appropriately set.

我们不能使用#[doc(hidden)]#[macro_export] macro_rules!自Rust 1.30起,bar_priv_impl __ 帮助宏并在帮助宏上使用#[cfg] ,因为用户现在可以请求使用mycrate :: bar; 仅导入 bar!宏,给出有关未定义 bar_priv_impl __!的错误.

We can't use a #[doc(hidden)] #[macro_export] macro_rules! bar_priv_impl__ helper macro and use #[cfg] on the helper macro since Rust 1.30, because users can now request use mycrate::bar; to only import the bar! macro, giving errors about how bar_priv_impl__! is not defined.

有什么方法比完整的宏复制更好吗?如果您要测试的N个功能真的很糟糕,因为您需要 2 n 个重复项.

Is there any way that's better than full macro duplication? It gets really bad if you have N features you're testing on, as you need 2n duplications.

推荐答案

由于Rust 1.30 [...],因为用户现在只能导入 bar!

实际上,该解决方案在Rust 1.30中仅 可行,因为它能够像普通的那样导入宏.请记住,您的宏还可以 具有 use 语句!:

Actually, this solution is only possible in Rust 1.30 because of the ability to import macros like normal. Remember that your macro can also have use statements!:

#[macro_export]
macro_rules! bar {
    ($val:expr) => {{
        use $crate::__bar_foo;
        __bar_foo!($val)
    }}
}

#[cfg(feature = "foo")]
#[macro_export]
macro_rules! __bar_foo {
    ($val:expr) => ($val + 1)
}

#[cfg(not(feature = "foo"))]
#[macro_export]
macro_rules! __bar_foo {
    ($val:expr) => ($val - 1)
}

您还可以完全限定助手宏的调用:

You can also fully-qualify your helper macro invocation:

#[macro_export]
macro_rules! bar {
    ($val:expr) => ($crate::__bar_foo!($val))
}

这篇关于如何有条件地更改Rust宏的一小部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆