gpt4 book ai didi

pointers - 将实现特征的数据存储在向量中

转载 作者:行者123 更新时间:2023-11-29 08:07:14 27 4
gpt4 key购买 nike

总体而言,我对 Rust 和系统语言非常陌生。我目前正在研究 Rust 来探索这门语言。我有一个我无法自己解决的问题。而且我想我已经了解问题所在。

我不想存储实现 trait BaseStuff 的对象在一个向量中。在 Rust 中对我来说不是一个简单的任务:-)。

这是我无法编译的示例代码。

trait BaseStuff {}

struct MyStuff {
value: i32,
}

struct AwesomeStuff {
value: f32,
text: String,
}

impl BaseStuff for MyStuff {}

impl BaseStuff for AwesomeStuff {}

struct Holder {
stuff: Vec<BaseStuff>,
}

impl Holder {
fn register(&mut self, data: impl BaseStuff) {
self.stuff.push(data);
}
}

fn main() {
let my_stuff = MyStuff { value: 100 };

let awesome_stuff = AwesomeStuff {
value: 100.0,
text: String::from("I'm so awesome!"),
};

let mut holder = Holder { stuff: vec![] };

holder.register(my_stuff);
}

error[E0277]: the size for values of type (dyn BaseStuff + 'static) cannot be known at compilation time --> src\main.rs:17:5 | 17 |
stuff: Vec, // unknown size | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait std::marker::Sized is not implemented for (dyn BaseStuff +
'static)
= note: to learn more, visit https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait = note: required by std::vec::Vec

error: aborting due to previous error

For more information about this error, try rustc --explain E0277. error: Could not compile playground.

The compiler message is clear and I understand the message. I can implement the trait BaseStuff in any struct I want't so its unclear which size it is. Btw the link isn't helpful because its pointing to outdated site...

String 的大小也是未知的,但 String 实现了特征 std::marker::Sized这就是为什么 Vec<String>将毫无问题地工作。对吗?

在 Rust 书中,我阅读了大小未知的数据类型,我必须将这些数据存储在堆上而不是堆栈上。我更改了我的代码如下。

struct Holder {
stuff: Vec<Box<BaseStuff>>,
}

impl Holder {
fn register(&mut self, data: impl BaseStuff) {
self.stuff.push(Box::new(data));
}
}

现在我遇到了一个新的编译器问题:

error[E0310]: the parameter type impl BaseStuff may not live long enough --> src\main.rs:22:25 | 21 | fn register(&mut self, data: impl BaseStuff) { |
--------------- help: consider adding an explicit lifetime bound impl BaseStuff: 'static... 22 | self.stuff.push(Box::new(data));
| ^^^^^^^^^^^^^^ | note: ...so that the type impl BaseStuff will meet its required lifetime bounds --> src\main.rs:22:25 | 22 | self.stuff.push(Box::new(data));
| ^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try rustc --explain E0310. error: Could not compile playground.

知道我出局了...我读了关于生命周期的书,并用 'a 更改了我的代码很多这里和'a以任何组合但没有运气......我不想写下我尝试过的任何生命周期定义组合。我不明白为什么我需要生命周期定义。所有权在任何步骤中都会移动,因此据我了解,很明显 Holder 结构是所有数据的所有者。是吗?

如何更正我的代码以进行编译?

感谢您的帮助。

最佳答案

几乎明白了 - 这里的问题是 BaseStuff 实现的类型可能是一个引用(例如 impl BaseStuff for &SomeType).这意味着即使您按值传递 data,该值也可能是一个引用,它会被您的 Box 淘汰。

解决这个问题的方法是添加一个约束,使对象具有 'static 生命周期,这意味着它要么是值类型,要么是静态引用。您可以将此约束应用于特征或接受特征的方法,具体取决于您的用例。

将约束应用于特征:

trait BaseStuff: 'static {}

将约束应用于方法:

impl Holder {
fn register(&mut self, data: impl BaseStuff + 'static) {
self.stuff.push(Box::new(data));
}
}

如果将 'static 约束添加到方法中,我建议也将其添加到 Vec 中以避免丢失类型信息,如下所示:

struct Holder {
stuff: Vec<Box<dyn BaseStuff + 'static>>,
}

关于pointers - 将实现特征的数据存储在向量中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54788384/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com