2017-12-06 16 views
3

デフォルト値を作成し、内部のバッファを反復する汎用関数を作成しようとしています。 "これは、引数も戻り値もない関数内で起こります。私は生涯が間違って宣言されているように見え、これを正しく機能させるには苦労している。コンテナを作成し、アイテムを追加し、アイテムを反復する汎用関数で値が十分に長く存続しない

DefaultおよびIntoIterator形質を実装するタイプのタイプと、1つのメソッドを必要とするFooという新しい特性があります。

trait Foo<T> { 
    fn add(&mut self, T); 
} 

struct FooBar<T> { 
    buf: Vec<Option<T>>, 
    len: usize, 
} 

impl<T> FooBar<T> { 
    fn new() -> Self { 
     let buf = Vec::new(); 
     let len = 0; 
     Self { buf, len } 
    } 

    fn iter(&self) -> FooBarIter<T> { 
     FooBarIter { foo: self, pos: 0 } 
    } 
} 

impl<T> Foo<T> for FooBar<T> { 
    fn add(&mut self, val: T) { 
     self.buf.push(Some(val)); 
     self.len += 1; 
    } 
} 

impl<T> Default for FooBar<T> { 
    fn default() -> Self { 
     Self::new() 
    } 
} 

impl<'a, T: 'a> IntoIterator for &'a FooBar<T> { 
    type Item = &'a T; 
    type IntoIter = FooBarIter<'a, T>; 

    fn into_iter(self) -> Self::IntoIter { 
     self.iter() 
    } 
} 

FooBarは、所有するベクトルに値を追加するだけです。無駄な反復のみを可能にするために、私は反復子を定義して、基礎となるVecを借用し、反復中に "現在の"インデックスを維持し、消費者が借りる各要素への参照を返します。

struct FooBarIter<'a, T: 'a> { 
    foo: &'a FooBar<T>, 
    pos: usize, 
} 

impl<'a, T> Iterator for FooBarIter<'a, T> { 
    type Item = &'a T; 

    fn next(&mut self) -> Option<Self::Item> { 
     if self.foo.len <= self.pos { 
      return None; 
     } 

     self.pos += 1; 
     self.foo.buf[self.pos - 1].as_ref() 
    } 
} 

総称関数は、参照によってそれらしかし反復処理し、その後、デフォルト値を作成します(タイプ&strの)いくつかの項目を追加します。 Rustが借りた金額FooBarが十分に長く生きていないと訴えるので、私は生涯を間違って宣言したようです。しかし、それは機能の終わりまで生きていると言われています。だから、Rustが実際に借りることを期待している時間は混乱しています。ここで

fn start<'a, T: 'a>() 
where 
    T: Foo<&'a str> + Default, 
    &'a T: IntoIterator<Item = &'a &'a str>, 
{ 
    let mut f = T::default(); 
    f.add("abcd"); 
    f.add("efgh"); 

    for val in &f { 
     println!("{}", *val); 
    } 

    f.add("ijkl"); 

    for val in &f { 
     println!("{}", *val); 
    } 
} 

fn main() { 
    start::<FooBar<&str>>(); 
} 

関数の最後に「借り値だけまで住んでいる」ので、その&fが十分に長く住んでいないことを示すエラーです。

error[E0597]: `f` does not live long enough 
    --> src/main.rs:70:17 
    | 
70 |  for val in &f { 
    |    ^does not live long enough 
... 
73 | } 
    | - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 61:1... 
    --> src/main.rs:61:1 
    | 
61 |/fn start<'a, T: 'a>() 
62 | | where 
63 | |  T: Foo<&'a str> + Default, 
64 | |  &'a T: IntoIterator<Item = &'a &'a str>, 
... | 
72 | |  } 
73 | | } 
    | |_^ 

私も&'a IntoIterator形質について異なる寿命パラメータを設定しようとしたが、その後、私は他のエラーのためのサークルで回って結局、本当に正しいの寿命を設定するに近づいていません。

私がFooBarで達成しようとしていることをさらに説明するために、ここにFooBarVecだった場合、私がしようとしていることの例があります。

fn start() { 
    let mut f = Vec::new(); 
    f.push("abcd"); 
    f.push("efgh"); 

    for val in &f { 
     println!("{}", *val); 
    } 

    f.push("ijkl"); 

    for val in &f { 
     println!("{}", *val); 
    } 
} 

生涯のパラメータを把握しようとすると正しい軌道上にいるのですか、それとも完全に何かありますか?

答えて

1

あなたが試みていることは現在不可能であると私は信じています。 startに渡されたとき、発信者が寿命を指定しているためで起動するには

、あなたのエラーメッセージは次のとおりです。

fn start<'a, T: 'a>() 

、発信者寿命を制御することはできませんので、これはどんな意味がありません。たとえば、呼び出しがstart::<Vec<&'static str>>だったが、関数が一時的な値を作成した場合はどうなりますか?このライフタイムは、イテレータの実装にも関連付けられています。呼び出し側が指示している限り、値の参照が存続する場合、反復処理が可能です。

多くの同様の場合において、より高いランクの形質はが溶液である境界は、しかし、私が得ることができる最も近いビット異なります

trait Foo<T> { 
    fn add(&mut self, T); 
} 

impl<T> Foo<T> for Vec<T> { 
    fn add(&mut self, val: T) { 
     self.push(val); 
    } 
} 

fn start<T>() 
where 
    T: Default + Foo<&'static str>, 
    for<'a> &'a T: IntoIterator, 
    for<'a, 'b> &'a <&'b T as IntoIterator>::Item: std::fmt::Display, 
{ 
    let mut f = T::default(); 
    f.add("abcd"); 
    f.add("efgh"); 

    for val in &f { 
     println!("{}", &val); 
    } 

    f.add("ijkl"); 

    for val in &f { 
     println!("{}", &val); 
    } 
} 

fn main() { 
    start::<Vec<&str>>(); 
} 

主付着点はT: Default + Foo<&'static str>あります。私が見る限り、Tの具体的な型を渡す方法はありませんが、その関数で定義されたHRTBを使用することができます。この場合、'staticを使用できます。我々はfor <'a> T: Default + Foo<&'a str>を使用しようとした場合、我々は、エラーを取得:

error[E0277]: the trait bound `for<'a> std::vec::Vec<&str>: Foo<&'a str>` is not satisfied 
    --> src/main.rs:33:5 
    | 
33 |  start::<Vec<&str>>(); 
    |  ^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a str>` is not implemented for `std::vec::Vec<&str>` 
    | 
    = help: the following implementations were found: 
      <std::vec::Vec<T> as Foo<T>> 
    = note: required by `start` 

コンパイラが寿命を一致させるために知っていないHRTBで指定されたものと呼び出しサイトで宣言。私は信じていますが、確信が持たれていないと、generic associated typesが問題を解決するかもしれません。

0

HRTBを使用して正しい方向に私を指し示すためにShepmasterに感謝します。その話題を読んだら、その機能自体にFooBarIterFooBarIter::Itemの寿命を提供させることができました。 FooBarIterを今から借用し、最後まで機能させることができます。 FooBarの有効期間は依然として発信者によって提供されます。

これは私がこれを最終的にコンパイルするために必要な唯一の変更です。

fn start<'a, T>() 
where 
    T: Foo<&'a str> + Default, 
    for<'b> &'b T: IntoIterator<Item = &'b &'a str>, 
{ 
    let mut f = T::default(); 
    f.add("abcd"); 
    f.add("efgh"); 

    for val in &f { 
     println!("{}", *val); 
    } 

    f.add("ijkl"); 

    for val in &f { 
     println!("{}", *val); 
    } 
} 
関連する問題