ベクトルのベクトルでも均一な型を持つベクトルに特性オブジェクトを渡すにはどうすればよいですか?

Aug 16 2020

これを簡潔に説明するのは本当に難しいです。しかし、私が欲しいのは、Vec "A"内に別のVec "B"を持つスレッドのベクトルを含むVec "A"のフィールドを持つ構造体です。Vec "A"は、Vec "B"とスレッドハンドルの両方を保持します。Vec "B"は均一なタイプであり、特性オブジェクトは必要ありませんが、Vec "A"は、特性オブジェクトを使用して複数の異なるタイプのVec "B"を保持します。基本的に、Vec "B"にはトレイトオブジェクトを使用したくありませんが、Vec "A"にはトレイトオブジェクトを使用します。

上記を実装しようとしましたが、必ずしも正しいとは限らず、エラーが発生します。これの実際の実装またはこれの直接的な回避策はありますか?

検索してみましたが、グーグルに短い段落を書かないと簡潔に言えない気がします。

これが私がそれがどのようにあるべきだと思うかの(擬似)コードです:

trait Tag {}

impl Tag for u32 {}
impl Tag for i64 {}


// Vec "B"
type InnerVec<T: Tag> = Vec<T>;

struct ThreadPool {
    // Vec "A"
    threads: Vec<(JoinHandle<()>, InnerVec<dyn Tag>)>,
}

回答

1 Locke Aug 16 2020 at 07:57

したがって、最初に、タイプエイリアスは新しいタイプではありません。これは、長い型名を支援するための検索および置換システムのようなものです(例:) type Foo<T> = FooSys<T, Vec<T>, u32>;。型の制約を追加できるとは思えません。

あなたの問題に関しては、あなたの擬似コードの最も直接的な解釈は、に寿命を追加することでしょうThreadPool

trait Tag {}

impl Tag for u32 {}
impl Tag for i64 {}


struct ThreadPool<'a> {
    threads: Vec<(JoinHandle<()>, Vec<Box<dyn Tag + 'a>>)>,
}

ただし、あなたが本当に知りたいと思うのは、非動的アイテムを含む動的VecのVecを格納する方法です。これを行うには、それを使用Anyして、必要なタイプにダウンキャストできます。詳細については、ドキュメントをご覧ください。

use std::any::Any;

struct ThreadPool {
    threads: Vec<(JoinHandle<()>, Box<dyn Any>)>,
}

impl ThreadPool {
    pub fn get_tags<T: 'static>(&self, index: usize) -> Option<&Vec<T>> {
        let (_, ref boxed) = self.threads[index];
        boxed.downcast_ref()
    }
}