我正在尝试实现看起来像这个最小例子的东西:
trait Bar<T> {}
struct Foo<T> {
data: Vec<Box<Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U: Bar<T>>(&mut self, x: U) {
self.data.push(Box::new(x));
}
}
Run Code Online (Sandbox Code Playgroud)
由于Rust默认为(据我所知)pass-by-ownership,我的心理模型认为这应该有效.该add方法获取对象的所有权,x并且能够将此对象移动到a中,Box因为它知道完整类型U(而不仅仅是特征Bar<T>).一旦进入a Box,框内项目的生命周期应该与框的实际生命周期相关联(例如,当pop()从矢量中删除时,对象将被销毁).
然而,很明显,编译器不同意(我确信比我更了解...),要求我考虑添加一个'static生命周期限定符(E0310).我99%肯定这不是我想要的,但我不确定我应该做什么.
为了澄清我的想法并帮助识别误解,我的心理模型来自C++背景,是:
Box<T> 本质上是 std::unique_ptr<T>Copy否则传递rvalue-reference&大致const&和&mut大致&She*_*ter 38
看看整个错误:
error[E0310]: the parameter type `U` may not live long enough
--> src/main.rs:9:24
|
8 | fn add<U: Bar<T>>(&mut self, x: U) {
| -- help: consider adding an explicit lifetime bound `U: 'static`...
9 | self.data.push(Box::new(x));
| ^^^^^^^^^^^
|
note: ...so that the type `U` will meet its required lifetime bounds
--> src/main.rs:9:24
|
9 | self.data.push(Box::new(x));
| ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
具体来说,编译器告诉您,某些任意类型U 可能包含引用,然后该引用可能变为无效:
impl<'a, T> Bar<T> for &'a str {}
fn main() {
let mut foo = Foo { data: vec![] };
{
let s = "oh no".to_string();
foo.add(s.as_ref());
}
}
Run Code Online (Sandbox Code Playgroud)
那将是坏消息.
您是否想要'static终生或参数化生命周期取决于您的需求.的'static寿命更容易使用,但有更多的限制.因此,当您在结构或类型别名中声明特征对象时,它是默认值:
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
// same as
// data: Vec<Box<dyn Bar<T> + 'static>>,
}
Run Code Online (Sandbox Code Playgroud)
但是,当用作参数时,特征对象使用生命周期省略并获得唯一的生命周期:
fn foo(&self, x: Box<dyn Bar<T>>)
// same as
// fn foo<'a, 'b>(&'a self, x: Box<dyn Bar<T> + 'b>)
Run Code Online (Sandbox Code Playgroud)
这两件事需要配对.
struct Foo<'a, T> {
data: Vec<Box<dyn Bar<T> + 'a>>,
}
impl<'a, T> Foo<'a, T> {
fn add<U>(&mut self, x: U)
where
U: Bar<T> + 'a,
{
self.data.push(Box::new(x));
}
}
Run Code Online (Sandbox Code Playgroud)
要么
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U>(&mut self, x: U)
where
U: Bar<T> + 'static,
{
self.data.push(Box::new(x));
}
}
Run Code Online (Sandbox Code Playgroud)
mca*_*ton 19
让我考虑添加一个'静态终身限定符(E0310).我99%肯定这不是我想要的,但我不确定我应该做什么.
是的.&'static它想要编译器不需要引用U: 'static.
具有U: 'static不U包含生命周期小于的引用的平均值'static.这是必需的,因为您希望将U实例放在没有生命周期的结构中.
trait Bar<T> {}
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U: Bar<T> + 'static>(&mut self, x: U) {
self.data.push(Box::new(x));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5891 次 |
| 最近记录: |