に自己参照を持つ状態を初期化しカプセル化します以下のように(故意に冗長)main()
にインラインで初期化される:を順次私は<code>RefCell</code>内に保持されて<code>Vec</code>のためのイテレータとして動作することができる構造体を定義しようとしている錆構造体
// Elided: lifetime parameter of Ref
let vec_ref: Ref<Vec<i32>> = holds_vec.vec_in_refcell.borrow();
// Elided: lifetime parameter of Iter
let mut vec_iter: Iter<i32> = vec_ref.iter();
の両方を保持しているIterator
を実装する構造体を定義する方法はあります(RefCell
を残したままにする)とIter
(のイテレータ状態を維持するため、Vec
などのイテレータをローリングするのではなく)、2番目のものが派生してから得られた参照を保持する最初?
私はこれを実装するためにいくつかの方法を試しましたが、すべては借用チェッカーと同じです。私は状態として裸構造体のメンバの両方の部分を入れた場合は、
struct HoldsVecInRefCellIter<'a> {
vec_ref: Ref<'a, Vec<i32>>,
vec_iter: Iter<'a, i32>,
}
のような、私はHoldsVecInRefCellIter { ... }
構文(例えばDoes Rust have syntax for initializing a struct field with an earlier field?を参照)で一度に両方のフィールドを初期化することはできません。私は
struct HoldsVecInRefCellIter<'a> {
vec_ref: Ref<'a, Vec<i32>>,
vec_iter: Option<Iter<'a, i32>>,
}
// ...
impl HoldsVecInRefCell {
// ...
fn iter(&self) -> HoldsVecInRefCellIter {
let mut new_iter = HoldsVecInRefCellIter { vec_ref: self.vec_in_refcell.borrow(), vec_iter: None };
new_iter.vec_iter = new_iter.vec_ref.iter();
new_iter
}
}
のような構造体で、順次初期化をシャントしようとすると、私はiter()
から返す防止構造体の可変自己ボローが発生します。この構造体の自己借用は、構造体の一部を安全に動かすことができない構造体の一部に参照を格納しようとした場合にも発生します(Why can't I store a value and a reference to that value in the same struct?)。これと比較すると、HoldsVecInRefCellIter
のような構造体のように見えますが、初期化を完了できれば、移動したときに正しいことが起こります。内部的にすべての参照は内部的にこの構造体よりも長いデータです。
は(https://internals.rust-lang.org/t/self-referencing-structs/418/3の例を参照)Rc
を使用して、自己参照を作成しないようにするトリックがありますが、あなたは直接の参照を保持するために実装されている既存のIterator
構造体を格納したい場合、私は、これらが適用される可能性がどのように表示されません基になるコンテナには、Rc
ではなく、
C++からのRust初心者として、これは頻繁に起きる問題のように感じられます(「コードブロックに複雑な状態の初期化ロジックがあり、そのロジックを抽象化して結果の状態を保持したい構造体に使用する」)。
関連質問:Returning iterator of a Vec in a RefCell
複雑な初期設定が一般的である - それは、通常、ビルダーパターンによって解決です。それはここでは問題ではありません。スライスの反復子は、存在する時間全体にわたってスライスへの参照を保持できることを期待しています。実際には、自分自身への参照を生成するイテレータを書くことはできません(http://stackoverflow.com/questions/25702909/can-i-write-an-iterator-that-yields-a-reference-into-itself)。 – Shepmaster
保存することができる 'fn borrow(&self) - > Ref>'メソッドを追加して、 'iter'をonにするか、イテレータを提供するクロージャを受け入れることができます:' fn iter (&self、f:F) ' –
Shepmaster
明確にする:私の意図は、イテレータが値を返すことであって、参照(例コードの' i32')ではない。私の挑戦は、基礎となるコンテナのための 'Iterator'を格納することによって値を生成することができるイテレータ構造体を初期化することでした。この例では、 'HoldsVecInRefCellIter'は' Ref> 'とベクトルへのインデックスだけを保持できますが、他の' Ref > 'はコンテナの' Iterator'を望むと思います。 –