Rust:有没有办法在宏类型参数上调用静态函数?

时间:2014-11-06 09:15:58

标签: macros rust

此代码:

#![feature(macro_rules)]

macro_rules! new(
    ($my_type:ty) => ( $my_type::new() );
)

struct Foo {
    blah: int
}

impl Foo {
    fn new() -> Foo {
        return Foo { blah: 0 }
    }
}

fn main() {
    let my_foo = new!(Foo);
    println!("Foo's value: {}", my_foo.blah);
}

看起来很好,但它失败并出现此错误:

test.rs:4:25: 4:32 error: unexpected token: `Foo`
test.rs:4     ($my_type:ty) => ( $my_type::new() );
                                  ^~~~~~~

如果我进入宏并将$my_type替换为Foo,它会编译并运行得很好,因此Foo在该位置显然有效。除非Foo显然来自宏观替换。

如果我运行rustc test.rs --pretty expanded,它就不会显示扩展的宏。它只是给了我相同的错误信息。我怀疑这意味着它在扩展宏之前生成了消息,但它可能只是除非编译成功,否则它不会显示任何内容。虽然这会严重限制--pretty expanded的有用性。

基于其他实验,我可以在基本上每个其他地方使用宏类型参数。你不能在它们上面调用静态函数。这似乎是一个相当随意的限制,错误信息肯定没有帮助。

为什么存在这种限制?它有办法吗?

1 个答案:

答案 0 :(得分:6)

Foo::bar()语法正在创建路径Foo::bar然后调用该函数,并且仅适用于有效路径,它不适用于任意类型,例如(u8, i8)::bar()不起作用。您可以使用ident宏非终端,该终端采用单个标识符,并且可以在标识符有效的情况下使用,包括在路径中

#![feature(macro_rules)]

macro_rules! new(
    ($my_type: ident) => ( $my_type::new() );
)

struct Foo {
    blah: int
}

impl Foo {
    fn new() -> Foo {
        return Foo { blah: 0 }
    }
}

fn main() {
    let my_foo = new!(Foo);
    println!("Foo's value: {}", my_foo.blah);
}

UFCS提供了通过语法<Type>::new()在任意类型上调用此类方法,因此,在实现时,用

替换当前的宏
macro_rules! new(
    ($my_type: ty) => ( <$my_type>::new() );
)

也应该有用。