如何重新定义宏?

5
在C++中,您可以取消定义和重新定义宏。例如,在视频游戏中常见的做法是在发布模式下将日志记录宏重新定义为无效。这可以确保代码完全消失,有助于提高性能。
在Rust中是否有类似的方法?
2个回答

9
基本上你可以这样做:
macro_rules! log_if_dbg {
    (...) => (if cfg!(debug_assertions) { /* do logging */ })
}

这是 debug_assert! 的实现方式。文档中说明:

与assert!不同,debug_assert!语句默认仅在非优化版本中启用。除非向编译器传递-C debug-assertions参数,否则优化版本将省略所有debug_assert!语句。这使得debug_assert!对于在发布版本中太昂贵的检查非常有用,但在开发过程中可能很有帮助。

这与您的情况相同,只是针对断言而不是日志记录。查看源代码
macro_rules! debug_assert {
    ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
}

这个问题在Rust用户论坛上也有简短讨论,在那里总结的是使用cfg(debug_assertions)来检查是否处于调试模式。但我不知道cfg(debug_assertions)有多稳定。

3
您将使用条件编译属性:
#[cfg(feature = "debugging")]
macro_rules! log {
    () => { println!("Debugging") }
}

#[cfg(not(feature = "debugging"))]
macro_rules! log {
    () => { }
}

fn main() {
    log!();
}

在这里,您可以使用Cargo的“特性”来提供一个编译时参数,以切换调试实现。然而,在这种情况下,没有必要使用宏。
#[cfg(feature = "debugging")]
fn log() { println!("Debugging") }

#[cfg(not(feature = "debugging"))]
fn log() {}

fn main() {
    log();
}

在这种情况下,我会非常信任优化器能够生成相同的代码。


1
不错的方法,肯定比 cfg(debug_assertions) 更清晰和更健壮。 - mdup
@mdup 和我们的回答也可以结合在一起。你可以使用 cfg(debug_assertions),就像我用 cfg(feature...) 一样。我的方法需要一些额外的工作,但你可以将其独立于发布模式启用。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接