使用 Traits 和 Trait 函数与切片和数组进行解除引用是如何工作的

问题描述 投票:0回答:1

(我是 Rust 新手,试图编写一个小纸牌游戏作为练习,但我可能没有正确掌握一些东西。我正在尽力解决我的问题/困惑。)

我想随机打乱一个向量。为此,我使用 rand 箱中的

shuffle
函数。

由于

shuffle
的另一个实现并希望通过特征名称来调用它,我遇到了一个问题,我偶然发现了一些有趣但令人困惑的东西:
shuffle
是由适用于 SliceRandom
 特征
实现的
 [T]
T
类型的切片),它没有为
Vec<T>
实现,但
Deref
特征为Vec<T>
实现
,通过将
Vec<T>
强制转换为
&[T]
充当桥梁, here也有说明。

fn main() {
    let mut vector_deck: Vec<u32> = (1..=24).collect::<Vec<u32>>();
    vector_deck.shuffle(&mut thread_rng());                    // 1 works
    SliceRandom::shuffle(&mut vector_deck, &mut thread_rng()); // 2 doesn't work

    let mut slice_deck: &mut [u32] = vector_deck.deref_mut();
    slice_deck.shuffle(&mut thread_rng());                     // 3 works
    SliceRandom::shuffle(slice_deck, &mut thread_rng());       // 4 works

    let mut array_deck: [u32; 24] = vector_deck.try_into().unwrap();
    array_deck.shuffle(&mut thread_rng());                     // 5 works
    SliceRandom::shuffle(&mut array_deck, &mut thread_rng());  // 6 doesn't work
}

这会导致

error[E0277]: the trait bound `Vec<u32>: SliceRandom` is not satisfied
  --> src\main.rs:36:26
   |
36 |     SliceRandom::shuffle(&mut vector_deck, &mut thread_rng()); // 2 doesn't work
   |     -------------------- ^^^^^^^^^^^^^^^^ the trait `SliceRandom` is not implemented for `Vec<u32>`
   |     |
   |     required by a bound introduced by this call
   |
   = help: the trait `SliceRandom` is implemented for `[T]`

error[E0277]: the trait bound `[u32; 24]: SliceRandom` is not satisfied
  --> src\main.rs:44:26
   |
44 |     SliceRandom::shuffle(&mut array_deck, &mut thread_rng()); // 6 doesn't work
   |     -------------------- ^^^^^^^^^^^^^^^ the trait `SliceRandom` is not implemented for `[u32; 24]`
   |     |
   |     required by a bound introduced by this call
   |
   = help: the trait `SliceRandom` is implemented for `[T]`

这就是困惑:

  1. 因为我之前提到的强制而有效,
  2. 不起作用,我不明白,因为据我了解,它应该像1一样工作,通过将其自身解引用为
    &[u32]
    ,但它会导致错误,所以我解引用了自己并且
  3. 工作原理与 1 相同,
  4. 按照我预期的方式工作 2 这使得它更加混乱,
  5. 其工作原理与 1 相同,
  6. 再次不起作用,虽然我有点希望这适用于数组,但由于数组本身不是切片,所以它与 2 中的问题完全相同?

那么取消引用究竟是如何工作的,以及由于不存在“解决方法”(

SliceRandom::shuffle(&mut array_deck, &mut thread_rng())
),我将如何在数组上使用
deref_mut()

arrays rust traits dereference coercion
1个回答
0
投票

可变解引用强制通常能够在每当

&mut T
时将
&mut U
变成
T: DerefMut<Target = U>
。通常,具有固定类型的函数调用将自行执行可变的 deref 强制转换,但在这种情况下,问题在于它是一个特征函数,因此参数的类型实际上并不知道 - 对于某些人来说这是
&mut Self
 Self
实现
SliceRandom
,Rust 通常不会推断只有一个符合条件的类型满足某个特征(即
&mut Vec<T>
只能可变地解引用为
&mut [T]
,并且
[T]
实现
SliceRandom
) — 这意味着
DerefMut
没有明确的目标类型。如果一个函数显式地采用
&mut U
来表示某些固定的
U
,那么只要
&mut T
,您就可以将
T: DerefMut<Target = U>
传递给它。

© www.soinside.com 2019 - 2024. All rights reserved.