有没有办法将类型名称放入 Rust 宏中?

wro*_*ame 3 rust

我有以下代码:

trait Trait {
    const NAME: &'static str;
    const VALUE: i64;
}

struct Struct1 {}
struct Struct2 {}

impl Trait for Struct1 {
    const NAME: &'static str = "Aardvark";
    const VALUE: i64 = 0;
}

impl Trait for Struct2 {
    const NAME: &'static str = "Zebra";
    const VALUE: i64 = 100;
}

macro_rules! print_static {
    ($n:expr, $v:expr) => {
        println!("Value of {} is {}", $n, $v);
    };
}

macro_rules! print_static2 {
    ($t:expr) => {
        println!("Value of {} is {}", $t::NAME, $t::VALUE);
    };
}

fn main() {
    print_static!(Struct1::NAME, Struct1::VALUE);
    print_static!(Struct2::NAME, Struct2::VALUE);

    //print_static2!(Struct1);
    //print_static2!(Struct2);
}
Run Code Online (Sandbox Code Playgroud)

它运行如下:

Value of Aardvark is 0
Value of Zebra is 100
Run Code Online (Sandbox Code Playgroud)

当我取消注释这些print_static2行时,我得到:

error: expected one of `,`, `.`, `?`, or an operator, found `::`
  --> src/main.rs:28:41
   |
28 |         println!("Value of {} is {}", $t::NAME, $t::VALUE);
   |                                         ^^ expected one of `,`, `.`, `?`, or an operator
...
37 |     print_static2!(Struct1);
   |     ------------------------ in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected one of `,`, `.`, `?`, or an operator, found `::`
  --> src/main.rs:28:41
   |
28 |         println!("Value of {} is {}", $t::NAME, $t::VALUE);
   |                                         ^^ expected one of `,`, `.`, `?`, or an operator
...
38 |     print_static2!(Struct2);
   |     ------------------------ in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)

有没有办法只指定类型名称一次,这样我就不会做这样的事情?

// Incorrectly associating Struct2's value with Struct1!
print_static!(Struct1::NAME, Struct2::VALUE);
Run Code Online (Sandbox Code Playgroud)

铁锈游乐场

Tav*_*nes 7

如果您想采用类型作为参数,请说:

macro_rules! print_static {
    ($t:ty) => {
        println!("Value of {} is {}", <$t>::NAME, <$t>::VALUE);
    };
}
Run Code Online (Sandbox Code Playgroud)

这是宏参数类型的完整列表

  • `&lt;$t as Trait&gt;` 可能更好地避免意外的名称冲突。 (6认同)
  • @wrongusername [示例](https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=8f63610705d597686ebcd43a8569fb72) (3认同)