2015-04-20 24 views
6

Aşağıdaki kod segmenti bana bir hata veriyor:Parametre tipi yeterince uzun süre canlı değil mi?

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>) 
    |    ^^^^^^^^^^^^^^^^ 

ama bu ince derler:

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

Hatanın nedeni nedir? Tek gerçek fark, operatörün as kullanımıdır. tip nasıl uzun süre canlı kalmaz? Bir ömür boyu parametresine sahip tüm olanlar: (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() 
    } 
} 

cevap

10

"uzun yaşamayacak" olabilir türlerinin bol aslında vardır.

Bu tip tanıtmak olsaydı:

struct ShortLivedBee<'a>; 
impl<'a> Animal for ShortLivedBee<'a> {} 

ShortLivedBee herhangi ömür boyu geçerli değil, ama aynı zamanda 'a için geçerlidir sadece onlar.

Yani ihtimaline karşı fonksiyonu içine bağlanmış

where T: Animal + 'static 

sadece ShortLivedBee Ben yem olabilir ile ShortLivedBee<'static> olduğunu.

Bunun nedeni, bir Box<Animal> oluştururken ilişkili bir yaşam süresine sahip olması gereken bir özellik nesnesi oluşturuyor olmanızdır. Bunu belirtmezseniz, varsayılan değer 'static olur. Yani tanımlı tür aslında:

sizin işlevi bağlı bir 'static T eklenir gerektirmektedir yüzden
type RcAnimal = Rc<Box<Animal + 'static>>; 

: Bir Box<Animal + 'static>'a = 'static sürece bir ShortLivedBee<'a> saklamak mümkün değildir. ömür boyu ilişkiler

type RcAnimal<'a> = Rc<Box<Animal + 'a>>; 

Ve açık şekilde işlevini değiştirmek:


Bir diğer yaklaşım böyle, senin RcAnimal için bir ömür boyu bir not eklemek olacaktır

fn new_rc_animal<'a, T>(animal: T) -> RcAnimal<'a> 
     where T: Animal + 'a { 
    Rc::new(Box::new(animal) as Box<Animal>) 
} 
+0

teşekkürler hızlı cevap için çok şey var ... Ama kısa ömürlü tipin kullanımı nedir? Derleyici üzerinde herhangi bir performans optimizasyonu yapabilir mi? – John

+1

Aslında kullanım, daha sonra bir tür yaşam boyu diğerine bağlanır. Örneğin, bir yineleyicinin ömrü, üzerinde yinelediğiniz nesnenin kullanım ömrüne bağlıdır ve bu, türüne yansıtılır. – Levans

+0

@JohnFrancis: Kısa ömürlü bir başka örnek: fonksiyonunuzdaki bir değişkenin referansı => değişken kısa ömürlü (fonksiyonun sonunda yok edilecektir) ve bu nedenle bunun için değer hesabına referanslar (Artık bu değişkeni artık bir kez referans vermekten kaçınmak için). –

İlgili konular