LoginSignup
2
2

More than 3 years have passed since last update.

RefCellに格納した値の参照を返す方法について

Last updated at Posted at 2021-01-23

Rustで連結リストを作成している際に,
連結リスト先頭から指定のインデックスの値を参照で返すのはどうすればいいのか調査したのでメモ

参考

もちろん, RefCellに持たせるT型の値にCopyトレイトを実装すれば参照でなくでもよい.

やり方

RefCellのborrow()はRef<'a, T>型を返す.
Ref<'a, T>はRefCellと同じライフタイムになる.

なので, Ref<'a, T>から取り出した値をメンバとして持ち,
かつそのメンバと同じライフタイムを設定した構造体Aを定義すればいい.

従って,

  1. RefCellから取り出したRef<'a, T>で構造体Aを作成する
  2. 構造体AはRef<'a, T>と同じライフタイムとなる
  3. これを返すことで, RefCellの値をコピーせずに参照できる.
  4. あとは構造体Aに適宜Derefを設定して, &Tへの参照となるようにする.

Borrow_mut()が返すRefMut<'a, T>にも同じ実装をすれば,
Re
fcellの値を変更できる可変参照が作れそう.

use std::ops::Deref;
use std::cell::{Ref, RefCell};

struct Foo {
    value: RefCell<i32>,
}

struct Foovalue<'a> {
    value: Ref<'a, i32>,
}

impl<'b> Deref for Foovalue<'b> {
    type Target = i32;
    fn deref(&self) -> &i32 {
        &self.value
    }
}

impl Foo {
    pub fn get_items(&self) -> Foovalue {
        Foovalue {
            value: self.value.borrow(),
        }
    }
}
fn main() {
    let f = Foo {
        value: RefCell::new(10),
    };
    let borrowed_f = &f;
    let items = borrowed_f.get_items();
    let v: &i32 = &items;
}

もちろん構造体でなくとも良い。
直接Ref<'a, T>derefを実装しても良い.

また, 連結リストのように目的の値を逐次探索する必要がなく,
一発でselfからアクセスできるのであれば, borrow()して返せば良い

まとめ

できるけど, これ多分生ポインタでやったほうが楽だ...
生ポインタを学習しよ...
Rustの循環参照周りを正攻法で攻めるとすごい大変...

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2