【问题标题】:How to redefine a macro?如何重新定义宏?
【发布时间】:2015-06-11 16:47:15
【问题描述】:

在 C++ 中,您可以取消定义和重新定义宏。 例如,在视频游戏中常见的做法是在发布模式下将日志记录宏重新定义为空。这保证了代码完全消失,这有助于提高性能。

有没有办法在 Rust 中做类似的事情?

【问题讨论】:

    标签: rust


    【解决方案1】:

    基本上你可以这样做:

    macro_rules! log_if_dbg {
        (...) => (if cfg!(debug_assertions) { /* do logging */ })
    }
    

    这就是the macro debug_assert! 的实现方式。医生说:

    与 assert! 不同,debug_assert!语句仅在非启用 默认情况下优化构建。优化的构建将省略所有 调试断言!语句,除非将 -C debug-assertions 传递给 编译器。这使得 debug_assert!对检查也很有用 在发布版本中出现的成本很高,但在发布期间可能会有所帮助 发展。

    这与您的情况相同,仅用于断言,而不用于记录。看着source

    macro_rules! debug_assert {
        ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); })
    }
    

    这在Rust users forum 上也有简要讨论,其中总结是cfg(debug_assertions) 是检查我们是否处于调试模式的方法。

    不过,我不知道cfg(debug_assertions) 有多稳定。

    【讨论】:

      【解决方案2】:

      您将使用条件编译属性:

      #[cfg(feature = "debugging")]
      macro_rules! log {
          () => { println!("Debugging") }
      }
      
      #[cfg(not(feature = "debugging"))]
      macro_rules! log {
          () => { }
      }
      
      fn main() {
          log!();
      }
      

      在这里,您可以使用Cargo's "features" 提供一个编译时参数,用于切换调试的实现。

      但是,在这种情况下,没有要求使用宏:

      #[cfg(feature = "debugging")]
      fn log() { println!("Debugging") }
      
      #[cfg(not(feature = "debugging"))]
      fn log() {}
      
      fn main() {
          log();
      }
      

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

      【讨论】:

      • 不错的方法,绝对比cfg(debug_assertions) 更干净、更健壮。
      • @mdup 和我们的答案也可以结合在一起。您可以使用cfg(debug_assertions),我的答案使用cfg(feature ...)。使用我的,还有一些额外的工作,但您可以在发布模式之外单独启用它。
      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 2019-08-05
      • 2021-07-26
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      相关资源
      最近更新 更多