我如何转换 Vec T ?到 Vec U不复制向量? [英] How do I convert a Vec<T> to a Vec<U> without copying the vector?

查看:30
本文介绍了我如何转换 Vec T ?到 Vec U不复制向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 Vec 转换为 Vec 其中 T 是某种原语,UT 的新类型:struct U(T).

I want to convert a Vec<T> to a Vec<U> where T is a primitive of some sort and U is a newtype of T: struct U(T).

我尝试过这样的事情:

struct Foo(u32);

fn do_something_using_foo(buffer: &mut Vec<Foo>) {}

fn main() {
    let buffer: Vec<u32> = vec![0; 100];

    do_something_using_foo(&mut buffer as Vec<Foo>);
}

我不想复制向量,我想将 u32 字段包装在 newtype Foo 中.

I don't want to make a copy of the vector, I want to wrap the u32 fields in the newtype Foo.

这给出了错误:

error[E0308]: mismatched types
 --> main.rs:8:28
  |
8 |     do_something_using_foo(&mut buffer as Vec<Foo>);
  |                            ^^^^^^^^^^^^^^^^^^^^^^^ expected mutable reference, found struct `std::vec::Vec`
  |
  = note: expected type `&mut std::vec::Vec<Foo>`
         found type `std::vec::Vec<Foo>`
  = help: try with `&mut &mut buffer as Vec<Foo>`

error: non-scalar cast: `&mut std::vec::Vec<u32>` as `std::vec::Vec<Foo>`
 --> main.rs:8:28
  |
8 |     do_something_using_foo(&mut buffer as Vec<Foo>);
  |                            ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error(s)

推荐答案

不能在安全的 Rust 中更改值的类型.不能保证这两种类型将具有相同的大小或相同的语义.

You cannot change the type of a value in place in safe Rust. There is no guarantee that the two types will have the same size or the same semantics.

这适用于单个值 (T -> U) 以及聚合值 (Vec -> >Vec, HashMap -> HashMap).请注意,聚合值实际上只是单个"值的特例.

This applies to a single value (T -> U) as well as aggregate values (Vec<T> -> Vec<U>, HashMap<K1, V1> -> HashMap<K2, V2>). Note that aggregate values are really just a special case of "single" values.

最好的办法是创建一个新的向量:

The best thing to do is to create a new vector:

let buffer2 = buffer.into_iter().map(Foo).collect();

您还可以调整 do_something_using_foo 以采用 Foou32 都实现的通用泛型类型:

You could also adjust do_something_using_foo to take in a common generic type that both Foo and u32 implement:

use std::borrow::{Borrow, BorrowMut};

#[derive(Debug, Clone)]
struct Foo(u32);

impl Borrow<u32> for Foo {
    fn borrow(&self) -> &u32 {
        &self.0
    }
}

impl BorrowMut<u32> for Foo {
    fn borrow_mut(&mut self) -> &mut u32 {
        &mut self.0
    }
}

fn do_something_using_foo<T>(buffer: &mut [T])
where
    T: BorrowMut<u32>,
{
}

fn main() {
    let mut buffer_u32 = vec![0u32; 100];
    let mut buffer_foo = vec![Foo(0); 100];

    do_something_using_foo(&mut buffer_u32);
    do_something_using_foo(&mut buffer_foo);
}

<小时>

在不安全的 Rust 中,这在技术上是可行的——你可以随心所欲地朝自己的脚开枪.


In unsafe Rust, it is technically possible — you can shoot yourself in the foot as much as you'd like.

你可以使用类似 std::mem 的东西::transmute 如果你知道你在做什么.

You can use something like std::mem::transmute if you know what you are doing.

然而,使用 transmuteVec 是未定义的行为,因为 Vec 的表示没有定义.相反,请参阅Sven Marnach 的回答.

However, it's undefined behavior to use transmute with Vec as the representation of Vec is not defined. Instead, see Sven Marnach's answer.

另见:

这篇关于我如何转换 Vec T ?到 Vec U不复制向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆