如何在编译时将ToString值转换为&str?

时间:2018-12-11 10:24:13

标签: rust constants

TL; DR:是否可以从const … &str的{​​{1}}创建const T


我喜欢在使用clap时提供默认值。但是,T : ToString需要将default_value用作clap,而不是原始类型:

&str

因此,如果它不是pub fn default_value(self, val: &'a str) -> Self ,则不能使用先前定义的const

&str

解决方法是改用use clap::{App, Arg}; /// The application's default port. pub const DEFAULT_LISTENER_PORT : u16 = 12345; fn main () { let matches = App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .arg(Arg::with_name("port") .short("p") .value_name("PORT") .default_value(DEFAULT_LISTENER_PORT) // < error here ).get_matches(); … }

&str

但是,这两个常数很容易不同步:

/// The application's default port.
pub const DEFAULT_LISTENER_PORT : u16 = 12345;

// Not public, since implementation detail.
const DEFAULT_LISTENER_PORT_STR : &str = "12345";

fn main () {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .arg(Arg::with_name("port")
             .short("p")
             .value_name("PORT")
             .default_value(DEFAULT_LISTENER_PORT_STR)
        ).get_matches();
     …
}

因此,我想通过魔术函数或宏从前者生成后者:

/// The application's default port.
pub const DEFAULT_LISTENER_PORT : u16 = 4579;

const DEFAULT_LISTENER_PORT_STR : &str = "12345"; // whoops

注意:由于std::string::ToString::to_string不是/// The application's default port. pub const DEFAULT_LISTENER_PORT : u16 = 4579; const DEFAULT_LISTENER_PORT_STR : &str = magic!(DEFAULT_LISTENER_PORT); ,因此不在范围内,但可以在主要方面提供解决方法,例如

const

但这也不符合人体工程学。

我是否缺少任何标准的宏或函数,或者尚无语言定义的方法来提供该功能?

1 个答案:

答案 0 :(得分:4)

您可以使用宏使用stringify!同时定义端口整数和字符串:

macro_rules! define_port {
    ($port:expr) => {
        pub const DEFAULT_LISTENER_PORT : u16 = $port;
        const DEFAULT_LISTENER_PORT_STR : &str = stringify!($port);
    }
}

define_port!(4579);

fn main() {
    println!("{}:{}", DEFAULT_LISTENER_PORT, DEFAULT_LISTENER_PORT_STR);
}

或者,如果您想要更通用的版本:

pub struct DefaultParam<T> {
    value: T,
    name: &'static str,
}

macro_rules! define {
    ( $name:ident : $t:ty = $val:expr ) => {
        pub const $name: DefaultParam<$t> = DefaultParam {
            value: $val,
            name: stringify!($val),
        };
    }
}

define!(PORT: u32 = 1234);

fn main() {
    println!("{} has the value: {}", PORT.name, PORT.value);
}