2016-10-14 5 views
16

漠然としたタイトルは申し訳ありませんが、私の問題を簡潔にまとめる方法を正確に知っていません。コンパイラは、パラメータの型が十分に長くは生きられない可能性があるため、静的なライフタイムを追加することを提案していますが、私はそれが私の望むものだとは思わない

私は(は、最小限の例を示す)何かを実装しようとしているが、次のようになります(私の知る限り)への錆のデフォルトは渡しの所有権ので

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

、私の精神的なモデルが考えていますこれはうまくいくはずです。 addメソッドはオブジェクトxの所有権を持ち、フルタイプUを知っているのでBoxにオブジェクトを移動できます(Bar<T>の特性だけでなく)。ボックス内に移動すると、ボックス内のアイテムの寿命は、ボックスの実際の寿命に結びつけられます(例えば、pop()がオブジェクトを破棄する場合)。

しかし、明らかにコンパイラは同意していません。私は'staticライフタイム修飾子(E0310)を追加することを検討するように頼んでいます。私は99%が私が欲しいものではないと確信していますが、私は何をすべきかを正確には分かりません。

は私が考えているものを明確にし、誤解を識別しやすくするために、私のモデルは、(私はC++の背景から来る)、本質的である:

  • Box<T>は、本質的に任意の注釈なしstd::unique_ptr<T>
  • で、変数がで渡されます値Copyと右辺参照もしそうでなければ
  • 参照アノテーションで、&はおおよそconst&&mut&
  • であります
  • デフォルトの寿命は

答えて

14

全体のエラーをチェックアウト:

error[E0310]: the parameter type `U` may not live long enough 
--> src/main.rs:9:24 
    | 
9 |   self.data.push(Box::new(x)); 
    |      ^^^^^^^^^^^ 
    | 
    = help: consider adding an explicit lifetime bound `U: 'static`... 
note: ...so that the type `U` will meet its required lifetime bounds 
--> src/main.rs:9:24 
    | 
9 |   self.data.push(Box::new(x)); 
    |      ^^^^^^^^^^^ 

は具体的には、コンパイラは、あなたがそれはいくつかの任意のタイプ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()); 
    } 
} 

これは悪いニュースです。

'staticライフタイムかパラメタライズドライフタイムのどちらを使用するかは、必要に応じて決まります。寿命は'staticですが、使用は簡単ですが制限があります。あなたは構造体の形質オブジェクトまたはタイプエイリアス宣言するときこのため、それはデフォルトです。しかし

struct Foo<T> { 
    data: Vec<Box<Bar<T>>>, 
    // same as 
    // data: Vec<Box<Bar<T> + 'static>>, 
} 

を、引数として使用する場合、形質オブジェクトは、生涯エリジオンを使用し、独自のを取得します生涯:

fn foo(&self, x: Box<Bar<T>>) 
// same as 
// fn foo<'a, 'b>(&'a self, x: Box<Bar<T> + 'b>) 

これらの2つのものが一致する必要があります。

struct Foo<'a, T> { 
    data: Vec<Box<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)); 
    } 
} 

または

struct Foo<T> { 
    data: Vec<Box<Bar<T>>> 
} 

impl<T> Foo<T> { 
    fn add<U>(&mut self, x: U) 
     where U: Bar<T> + 'static 
    { 
     self.data.push(Box::new(x)); 
    } 
} 
+0

ありがとう、それは大いにクリア! –

11

asking me to consider adding a 'static lifetime qualifier (E0310). I am 99% sure that's not what I want, but I'm not exactly sure what I'm supposed to do.

レキシカルスコープですはいそうです。コンパイラは&'static参照を望まないので、U: 'staticが必要です。

U: 'staticとすると、Uには、寿命が'static未満の参照は含まれません。これは、生涯を持たない構造体にUインスタンスを配置するために必要です。

trait Bar<T> {} 

struct Foo<T> { 
    data: Vec<Box<Bar<T>>> 
} 

impl<T> Foo<T> { 
    fn add<U: Bar<T> + 'static>(&mut self, x: U) { 
     self.data.push(Box::new(x)); 
    } 
} 
+0

ありがとう!それはとても役に立ちました - 私は答えがより完全であるために受け入れられた答えをShepmasterに与えるつもりですが、私はその説明に感謝します! –

+1

@RobertMasonより完全だったので、問題はありません、私は彼の答えも+1しました – mcarton

関連する問題

 関連する問題