rust 质关联类型无法索引

ymdaylpp  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(153)

我需要访问的数据是一个特征的关联类型,但是编译器显示关联的数据不能被索引。
我的意图是:实现GiveMat特性的示例,以便能够缓存mat字段中的数组数据,并且后续计算需要访问不同示例中的数据字段元素。我将遇到的问题简化为以下代码:

trait GiveMat {
    type Output;
    fn give_mat(&mut self) -> &Self::Output;
}

struct Arr2 {
    elem: i32,
    mat: Option<[i32; 2]>,
}

impl Arr2 {
    fn new(elem: i32) -> Arr2 {
        Arr2 { elem, mat: None }
    }

    fn calc_mat(&self) -> [i32; 2] {
        [self.elem, self.elem]
    }
}

impl GiveMat for Arr2 {
    type Output = [i32; 2];
    fn give_mat(&mut self) -> &Self::Output {
        if self.mat.is_none() {
            self.mat.get_or_insert(self.calc_mat())
        } else {
            self.mat.as_ref().unwrap()
        }
    }
}

struct Bowl<ArrT: GiveMat> {
    arrs: Vec<ArrT>,
    big_mat: Option<[i32; 4]>,
}

impl<ArrT: GiveMat> Bowl<ArrT> {
    fn new(arrs: Vec<ArrT>) -> Bowl<ArrT> {
        Bowl {
            arrs,
            big_mat: None,
        }
    }

    fn set_big_mat(&mut self) -> &[i32; 4] {
        let mats: Vec<_> = self.arrs.iter_mut().map(|x| x.give_mat()).collect();
        for i in 0..4 {
            if i < 2 {
                self.big_mat.unwrap()[i] = self.arrs[0].give_mat()[0][i]
            } else {
                self.big_mat.unwrap()[i] = mats[1][i % 2 as usize]
            }
        }
        self.big_mat.as_ref().unwrap()
    }
}

fn main() {
    let mut a = Arr2::new(10);
    println!("{:?}", a.give_mat());

    let mut b = Arr2::new(20);
    println!("{:?}", b.give_mat());

    let c = a.give_mat()[1] + b.give_mat()[1];
    println!("{}", c);
}

编译错误为:

Compiling playground v0.0.1 (/playground)
error[E0608]: cannot index into a value of type `&<ArrT as GiveMat>::Output`
  --> src/main.rs:49:44
   |
49 |                 self.big_mat.unwrap()[i] = self.arrs[0].give_mat()[0][i]
   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0608]: cannot index into a value of type `&<ArrT as GiveMat>::Output`
  --> src/main.rs:51:44
   |
51 |                 self.big_mat.unwrap()[i] = mats[1][i % 2 as usize]
   |                                            ^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0608`.
error: could not compile `playground` due to 2 previous errors
yhuiod9q

yhuiod9q1#

问题是你的ArrT类型是泛型的,它可以有任何Output,也可以返回i32。你可以进一步限制输出类型,使其可以被usize索引,并将trait更改为:

use core::ops::Index;
trait GiveMat {
    type Output: Index<usize>;
    fn give_mat(&mut self) -> &Self::Output;
}

这将允许您在Bowl的impl中编写self.arrs[0].give_mat()[0],但您会遇到与代码其余部分的类型不匹配。

相关问题