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();

但我们马上得到

error〔E0015〕:静态中的调用仅限于常量函数、元组结构和元组变体

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

impl Foo {
const fn const_new() -> Self { Self { } }
}
static FOO: Foo = Foo::const_new();

但特征功能的const双胞胎似乎很奇怪。有没有一种惯用的方法来编写/实现这样的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上的代码。

您可以将const_new重命名为仅new。当特征方法和固有方法具有相同的名称时,总是选择固有方法;它并不被认为是模棱两可的。

这样,可以在const和泛型上下文中编写相同的调用,并且没有异常名称。(我还建议记录这两个函数以提及彼此,这样人们就不会因为其中一个存在而认为另一个不存在。(

也就是说,我不能说这个想法是地道的我在我用过的图书馆里还没见过这样做。

根据Rust编译器的建议,这是惯用的解决方案:

use once_cell::sync::Lazy;
static FOO: Lazy<Foo> = Lazy::new(Foo::new);

游乐场

最新更新