编写自定义格式的最佳方式是什么!宏观?

What's the best way to write a custom format! macro?

我正在尝试创建一个自定义 crash! 宏,它基本上只是包装 eprintln!,但它可以是任何其他类似 format! 的宏。目前看起来像这样。

macro_rules! crash {
    ($fmt_str:literal, $($args:expr),*) => {{
        eprintln!($fmt_str, $args);
        std::process::exit(1);
    }};
}

我不能直接使用 $args,因为它还在重复,所以我需要一些方法来将它分开,但我不确定该怎么做。

原来我只是脑子一片空白,最后回答了我自己的问题。我只需要扩展 $args... 对于最终来到这里的其他人,解决方案如下所示:

macro_rules! crash {
    ($fmt_str:literal) => {{
        eprintln!($fmt_str);
        std::process::exit(1);
    }};

    ($fmt_str:literal, $($args:expr),*) => {{
        eprintln!($fmt_str, $($args),*);
        std::process::exit(1);
    }};
}

虽然您的解决方案有效,但转发宏参数的最佳方式是将它们捕获为 tt。在你的情况下,因为你想要的只是转发它们,你可以使用 $($t:tt)*:

macro_rules! crash {
    ($($t:tt)*) => {{
        eprintln!($($t)*);
        std::process::exit(1);
    }};
}

这样做的好处是它是完全透明的,并且可以启用底层宏启用的所有功能。例如,在这种情况下,tt 版本支持 early-expanded 格式字符串,而您的原始版本不支持 (playground):

// crash!(concat!("a", "b")); // Does not compile
crash_tt!(concat!("a", "b"));