首页 > 解决方案 > Rust:静态、常量、新和特征

问题描述

让我们有一个简单的特征:

trait Object {
    fn new() -> Self
    where
        Self: Sized;
}

并且结构实现了这个特征:

struct Foo { /* internal fields */ }

impl Object for Foo {
    fn new() -> Self {
        Self { /* some magic */ }
    }
}

现在我们要在 中声明静态变量main.rs,例如:

static FOO: Foo = Foo::new();

但我们立即得到

错误[ E0015 ]:静态调用仅限于常量函数、元组结构和元组变体

所以,如果我们要构造静态Foo类型的变量,我们应该声明一个类似的函数new,但它应该是不同的函数,例如:

impl Foo {
    const fn const_new() -> Self { Self { } }
}

static FOO: Foo = Foo::const_new();

但是const特征函数的-twins 似乎很奇怪。有没有一种惯用的方式来编写/实现这样const的对应物?

更新

为了清楚起见,我在这里扩展了@KevinReid 的答案。给定代码有效:

pub trait Object {
    fn new() -> Self;
}

pub struct Foo {}

impl Foo {
    pub const fn new() -> Self { // (1)
        Self {}
    }
}

impl Object for Foo {
    fn new() -> Self { // (2)
        println!("A-HA!");
        Self::new() // no recursion, calls (1)
    }
}

const FOO: Foo = Foo::new(); // calls (1)

fn main() {
    let obj: Foo = Object::new(); // calls (2)
    let foo = Foo::new(); // calls (1)
}

Rust Playground 上的这段代码

标签: rusttraits

解决方案


您可以重命名const_newnew. 当 trait 方法和固有方法同名时,总是选择固有方法;它不被认为是模棱两可的。

这样,同一个调用可以在 const 和泛型上下文中编写,并且没有不寻常的名称。(我还建议记录这两个函数以相互提及,所以人们不要假设因为一个存在而另一个不存在。)

也就是说,我不能说这个想法是惯用的。我还没有在我使用过的库中看到它。


推荐阅读