How to redefine a macro?

2019-06-25 09:53发布

In C++, you can undefine and redefine a macro. For example, a common thing to do in video games is to redefine the logging macro to nothing in Release mode. This guarantees that the code completely disappears which helps with performance.

Is there a way to do a similar thing in Rust?

标签: rust
2条回答
smile是对你的礼貌
2楼-- · 2019-06-25 10:51

Basically you might do:

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

This is how the macro debug_assert! is implemented. The doc says:

Unlike assert!, debug_assert! statements are only enabled in non optimized builds by default. An optimized build will omit all debug_assert! statements unless -C debug-assertions is passed to the compiler. This makes debug_assert! useful for checks that are too expensive to be present in a release build but may be helpful during development.

This is the same as your situation, only for assert, not logging. Looking at the source:

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

This has also been briefly discussed on the Rust users forum, where the summary is that cfg(debug_assertions) is the way to check if we're in debug mode.

I have no idea how stable cfg(debug_assertions) is, however.

查看更多
甜甜的少女心
3楼-- · 2019-06-25 10:53

You would use conditional compilation attributes:

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

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

fn main() {
    log!();
}

Here, you can use Cargo's "features" to provide a compile-time argument that switches the implementation of debugging.

However, there's no requirement to use macros in this case:

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

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

fn main() {
    log();
}

I'd trust pretty heavily in the optimizer to produce the same code in this case.

查看更多
登录 后发表回答