Cell<T>
は型はミュータブルでもイミュータブルでもT
値を変更可能な形で使うことができます。シングルスレッドでのみ使えます。
Cell
で値の取得と更新はそれぞれ::get
と::set
を使います。以下ではcell_i32
はイミュータブルでの定義ですが、それらメソッドを使って値の更新ができています。
use std::cell::Cell;
let cell_i32: Cell = Cell::new(33);
let ref_cell_i32 = &cell_i32;
cell_i32.set(cell_i32.get() + 1);
ref_cell_i32.set(ref_cell_i32.get() + 1);
{
let ref_cell_i32_in_scope = &cell_i32;
ref_cell_i32_in_scope.set(ref_cell_i32_in_scope.get() + 1);
}
assert_eq!(cell_i32.get(), 36);
しかし、ここでCell<String>
で同じようなコードを書いてみます。
use std::cell::Cell;
let cell_string: Cell = Cell::new("foo".into());
assert_eq!(cell_string.get(), "foo".to_string());
これは動きません。エラー文を見ると「::get
は有るけど、T
はstd::marker::Copy
実装してないよ」のように書いてあります。
the method
get
exists but the following trait bounds were not satisfied:std::string::String : std::marker::Copy
このことからCell<T>
のT
はstd::marker::Copy
を実装済の型を渡さなければ意味がありません。
もしstd::marker::Copy
な値を同じように扱いたいならRefCell<T>
があります。