私はいくつかのコードを書いていて、値を取るメソッドを持つ特性を持っていましたself
。Box
'd trait オブジェクトでこのメソッドを呼び出したい(Box
およびその値を消費する)。これは可能ですか?もしそうなら、どのように?
コードに関しては、最小限の例は次の (不完全な) コードのようになります。
trait Consumable {
fn consume(self) -> u64;
}
fn consume_box(ptr: Box<dyn Consumable>) -> u64 {
//what can I put here?
}
私の質問は、指定された署名を関数に入力して、返される値が'd 値consume_box
を呼び出すことによって取得される値になるようにする方法です。consume
Box
最初に書いていた
ptr.consume()
関数の本体として、これはまったく正しい考えではないことはわかっていBox
ますが、その内容だけでなく、それを消費したいという事実を理解していないため、それが私が考えることができる唯一のものです. これはコンパイルされず、エラーが発生します。
タイプ dyn 消耗品の値を移動できません: dyn 消耗品のサイズは静的に決定できません
Rust を初めて使用する私にとって、これは少し驚きでした。self
引数が C++ の右辺値参照と同様に渡されるのではないかと考えていました (これは本当に私が望んでいることです。C++ では、おそらく署名付きのメソッドによってこれを実装するでしょう)。virtual std::uint64_t consume() &&
、std::unique_ptr
仮想デストラクタを介して移動元オブジェクトをクリーンアップできるようにします)が、Rustは本当に値渡しであり、引数を前の場所に移動していると思います-したがって、コードを拒否するのは合理的です.
Box
問題は、 'd 特性オブジェクトを消費できる場所で、必要な動作を取得する方法がわからないことです。デフォルトの実装でトレイトにメソッドを追加しようとしましたが、vtable で何か便利なものが得られるかもしれないと考えました。
trait Consumable {
fn consume(self) -> u64;
fn consume_box(me: Box<Self>) -> u64 {
me.consume()
}
}
ただし、これによりエラーが発生します
特性
Consumable
をオブジェクトにすることはできません
型について言及すると、Box<dyn Consumable>
これはそれほど驚くべきことではありません。引数の型が変化する関数をどう処理するかをコンパイラが判断するのSelf
は奇跡的だったからです。
提供された署名を使用して関数を実装することは可能consume_box
ですか?必要に応じて特性を変更することもできますか?
有用な場合、より具体的には、これはいくつかの数式の一種の表現の一部です。おもちゃのモデルは、大まかに次のような特定の実装になる可能性があります。
impl Consumable for u64 {
fn consume(self) -> u64 {
self
}
}
struct Sum<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Sum<A, B> {
fn consume(self) -> u64 {
self.0.consume() + self.1.consume()
}
}
struct Product<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Product<A, B> {
fn consume(self) -> u64 {
self.0.consume() * self.1.consume()
}
}
fn parse(&str) -> Option<Box<dyn Consumable> > {
//do fancy stuff
}
ここで、ほとんどの場合、物事は単純な古いデータです(ただし、ジェネリックのために、潜在的にその大きなブロックです)が、これをこれらの種類のものへのより不透明なハンドルを渡すことと互換性があるようにするため、欲求で作業できるようにしBox<dyn Consumable>
ます。少なくとも言語レベルでは、これは私がやっていることの良いモデルです - これらのオブジェクトが所有する唯一のリソースはメモリの断片です (マルチスレッドとは何の関係もありませんし、自己参照的な悪ふざけもありません) - これはモデルは、私が持っているユースケースが、単にオブジェクトを読み取るのではなく、実装がオブジェクトを消費するのに役立つものであることを把握しておらず、「オープン」が必要であることを適切にモデル化していませんenum
それはツリーを直接表します) - したがって、参照渡しに書き直そうとするのではなく、値渡しについて尋ねているのはなぜですか。