我如何转换 Vec T ?到 Vec U不复制向量? [英] How do I convert a Vec<T> to a Vec<U> without copying the vector?
问题描述
我想将 Vec
转换为 Vec
其中 T
是某种原语,U
是 T
的新类型: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
以采用 Foo
和 u32
都实现的通用泛型类型:
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.
然而,使用 transmute
和 Vec
是未定义的行为,因为 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屋!