Vec<Box<dyn Trait>>
を入力として使用し、その要素をVec<Rc<RefCell<dyn Trait>>>
。それを行う最良の方法は何ですか?
私が試した:
use std::cell::RefCell;
use std::rc::Rc;
trait Trait {}
fn main() {
let mut source: Vec<Box<dyn Trait>> = Vec::new();
let mut dest: Vec<Rc<RefCell<dyn Trait>>> = Vec::new();
for s in source {
let d = Rc::new(RefCell::new(s.as_ref()));
dest.Push(d);
}
}
しかし、私はエラーを受け取りました:
error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
--> src/main.rs:12:19
|
12 | dest.Push(d);
| ^ the trait `Trait` is not implemented for `&dyn Trait`
|
= note: required for the cast to the object type `dyn Trait`
実際に可能ですか、それとも入力タイプを変更する必要がありますか?
Trait
を制御する場合の1つのオプションは、内部の実装を遅延させることで、Box<dyn Trait>
に実装することです。
// We could implement Trait only for Box<dyn Trait>, but usually what you want
// is to implement it for all Boxes of things that are Trait instead
impl<T: ?Sized + Trait> Trait for Box<T> {}
fn pushes(dest: &mut Vec<Rc<RefCell<dyn Trait>>>, source: Vec<Box<dyn Trait>>) {
for s in source {
dest.Push(Rc::new(RefCell::new(s)));
}
}
これは、すでにBox
edオブジェクトを2番目のポインター(Rc
)の後ろにラップすることに注意してください。パフォーマンスに依存するアルゴリズムでdest
を使用している場合は、1回ではなく2回逆参照する必要があります。 Box<T: Trait>
を受け入れることができるようにコードを再構成できる場合、T
をBox
からRefCell
に移動することにより、二重の間接参照を排除できます。
?Sized
が必要な理由を説明しています)_RefCell<dyn Trait>
_は有効なタイプですが、 _RefCell<T>
_ の宣言により_T: ?Sized
_が許可されるため、現在、モジュールの外部から作成する方法はありません。 CoerceUnsized
以外、サイズ付きの値で開始する必要があります。
ただし、unsafe
コードを使用して Cell
または UnsafeCell
に変換できるはずです。 #[repr(transparent)]
。