简体   繁体   中英

Interpolate `ident` in string literal in `macro_rules!`

Is it possible to interpolate a macro_rules! variable, of type ident , into a string literal in a macro? In other words is it possible to "escape" the double quotes of the literal?

// `trace_macros!` requires nightly
#![feature(trace_macros)]
trace_macros!(true);

macro_rules! export_mod_if_feature {
    ($system:ident) => {
        #[cfg(target_os = "$system")] // <-- problem is here
        pub mod $system;
    };
}

export_mod_if_feature!(linux);

// ... should translate to:
#[cfg(target_os = "linux")]
pub mod linux;

// ... but instead it becomes:
#[cfg(target_os = "$system")]
pub mod linux;`

I have tried using #[cfg(target_os = stringify!($system))] but the cfg requires an actual string literal after target_os = , not just a compile-time string.

Since the cfg attribute expects a literal and the pub mod expects a ident , I think you can use two values as the input of your macro and match one as a literal metavariable and the other as a ident metavariable. This would be more flexible when the names of the feature and the module are different.

#![feature(trace_macros)]
trace_macros!(true);

macro_rules! export_mod_if_feature {
    ($system:literal, $module:ident) => {
        #[cfg(target_os = $system)]
        pub mod $module;
    };
}

export_mod_if_feature!("linux", linux);

Playground

Yes, the stringify.(...) macro does that, so also this thread .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM