参数类型可能活得不够长?
Parameter type may not live long enough?
下面的代码段给我一个错误:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
type RcAnimal = Rc<Box<Animal>>;
fn new_rc_animal<T>(animal: T) -> RcAnimal
where
T: Animal /* + 'static */ // works fine if uncommented
{
Rc::new(Box::new(animal) as Box<Animal>)
}
fn main() {
let dog: RcAnimal = new_rc_animal(Dog);
let cat: RcAnimal = new_rc_animal(Cat);
let mut v: Vec<RcAnimal> = Vec::new();
v.push(cat.clone());
v.push(dog.clone());
for animal in v.iter() {
println!("{}", (**animal).make_sound());
}
}
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:8:13
|
4 | fn new_rc_animal<T>(animal: T) -> RcAnimal
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/main.rs:8:13
|
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
但这编译得很好:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
fn new_rc_animal<T>(animal: T) -> Rc<Box<T>>
where
T: Animal,
{
Rc::new(Box::new(animal))
}
fn main() {
let dog = new_rc_animal(Dog);
let cat = new_rc_animal(Cat);
}
错误的原因是什么?唯一真正的区别似乎是运算符 as
的使用。 类型怎么可能活不长? (playground)
// Definition of Cat, Dog, and Animal
trait Animal {
fn make_sound(&self) -> String;
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) -> String {
"meow".to_string()
}
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) -> String {
"woof".to_string()
}
}
附录
澄清一下,我有两个问题:
- 为什么这行不通? ...已在接受的答案中解决。
- type 与值或引用相比,怎么可能是短暂的? ...在评论中提到了这一点。剧透:type 只是存在,因为它是一个编译时概念。
实际上有很多类型可以"not live long enough":所有类型都有生命周期参数。
如果我介绍这个类型:
struct ShortLivedBee<'a>;
impl<'a> Animal for ShortLivedBee<'a> {}
ShortLivedBee
对任何生命周期都无效,但仅对 'a
有效。
所以在你的情况下
where T: Animal + 'static
我唯一可以输入你函数的 ShortLivedBee
是 ShortLivedBee<'static>
。
造成这种情况的原因是,在创建 Box<Animal>
时,您正在创建一个特征对象,该对象需要具有关联的生命周期。如果不指定,则默认为 'static
。所以你定义的类型其实是:
type RcAnimal = Rc<Box<Animal + 'static>>;
这就是为什么您的函数需要将 'static
边界添加到 T
的原因:无法将 ShortLivedBee<'a>
存储在 [=24= 中] 除非 'a = 'static
.
另一种方法是向您的 RcAnimal
添加生命周期注释,如下所示:
type RcAnimal<'a> = Rc<Box<Animal + 'a>>;
并更改您的函数以明确生命周期关系:
fn new_rc_animal<'a, T>(animal: T) -> RcAnimal<'a>
where T: Animal + 'a {
Rc::new(Box::new(animal) as Box<Animal>)
}
下面的代码段给我一个错误:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
type RcAnimal = Rc<Box<Animal>>;
fn new_rc_animal<T>(animal: T) -> RcAnimal
where
T: Animal /* + 'static */ // works fine if uncommented
{
Rc::new(Box::new(animal) as Box<Animal>)
}
fn main() {
let dog: RcAnimal = new_rc_animal(Dog);
let cat: RcAnimal = new_rc_animal(Cat);
let mut v: Vec<RcAnimal> = Vec::new();
v.push(cat.clone());
v.push(dog.clone());
for animal in v.iter() {
println!("{}", (**animal).make_sound());
}
}
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:8:13
|
4 | fn new_rc_animal<T>(animal: T) -> RcAnimal
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/main.rs:8:13
|
8 | Rc::new(Box::new(animal) as Box<Animal>)
| ^^^^^^^^^^^^^^^^
但这编译得很好:
use std::rc::Rc;
// Definition of Cat, Dog, and Animal (see the last code block)
// ...
fn new_rc_animal<T>(animal: T) -> Rc<Box<T>>
where
T: Animal,
{
Rc::new(Box::new(animal))
}
fn main() {
let dog = new_rc_animal(Dog);
let cat = new_rc_animal(Cat);
}
错误的原因是什么?唯一真正的区别似乎是运算符 as
的使用。 类型怎么可能活不长? (playground)
// Definition of Cat, Dog, and Animal
trait Animal {
fn make_sound(&self) -> String;
}
struct Cat;
impl Animal for Cat {
fn make_sound(&self) -> String {
"meow".to_string()
}
}
struct Dog;
impl Animal for Dog {
fn make_sound(&self) -> String {
"woof".to_string()
}
}
附录
澄清一下,我有两个问题:
- 为什么这行不通? ...已在接受的答案中解决。
- type 与值或引用相比,怎么可能是短暂的? ...在评论中提到了这一点。剧透:type 只是存在,因为它是一个编译时概念。
实际上有很多类型可以"not live long enough":所有类型都有生命周期参数。
如果我介绍这个类型:
struct ShortLivedBee<'a>;
impl<'a> Animal for ShortLivedBee<'a> {}
ShortLivedBee
对任何生命周期都无效,但仅对 'a
有效。
所以在你的情况下
where T: Animal + 'static
我唯一可以输入你函数的 ShortLivedBee
是 ShortLivedBee<'static>
。
造成这种情况的原因是,在创建 Box<Animal>
时,您正在创建一个特征对象,该对象需要具有关联的生命周期。如果不指定,则默认为 'static
。所以你定义的类型其实是:
type RcAnimal = Rc<Box<Animal + 'static>>;
这就是为什么您的函数需要将 'static
边界添加到 T
的原因:无法将 ShortLivedBee<'a>
存储在 [=24= 中] 除非 'a = 'static
.
另一种方法是向您的 RcAnimal
添加生命周期注释,如下所示:
type RcAnimal<'a> = Rc<Box<Animal + 'a>>;
并更改您的函数以明确生命周期关系:
fn new_rc_animal<'a, T>(animal: T) -> RcAnimal<'a>
where T: Animal + 'a {
Rc::new(Box::new(animal) as Box<Animal>)
}