我想转换一个Vec
我尝试了这样的方法:
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
字段包装在newtypeFoo
。
这给出了错误:
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)
根据< code > STD::mem::transduce()的文档,从Rust 1.38开始,使用< code>Vec::from_raw_parts结合< code>ManuallyDrop是最佳选择:
let v_from_raw = unsafe {
// Ensure the original vector is not dropped.
let mut v_clone = std::mem::ManuallyDrop::new(v_orig);
Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut U,
v_clone.len(),
v_clone.capacity())
};
这样做的先决条件是 T
和 U
具有相同的大小、相同的最小对齐方式,并且对 T
有效的所有位模式也对 U
有效。如果您在问题中定义 T
和 U
,则无法保证这一点。
struct U(T)
定义了一个元组结构,这种结构的内存布局是完全未定义的。但是,通过使用透明
表示,可以强制内存表示相同:
#[repr(transparent)]
struct U(T);
Nightly Rust拥有<code>Vec::into_raw_parts</code>,这减少了代码量和出错的地方:
#![feature(vec_into_raw_parts)]
fn convert_using_into_raw_parts(v: Vec<T>) -> Vec<U> {
let (ptr, len, cap) = v.into_raw_parts();
unsafe { Vec::from_raw_parts(ptr as *mut U, len, cap) }
}
不能在“安全保护”中就地更改值的类型。无法保证这两种类型具有相同的大小、对齐方式或语义。
这适用于单个值(< code>T)
最直接的解决方案:
let buffer2 = buffer.into_iter().map(Foo).collect();
在编译器可以判断您实际上没有更改重要内容的情况下,这实际上变成了无操作:
fn convert(b: Vec<u32>) -> Vec<Foo> {
b.into_iter().map(Foo).collect()
}
通过优化x86_64 Rust 1.54 的程序集输出:
playground::convert:
movq %rdi, %rax
movq (%rsi), %rcx
movups 8(%rsi), %xmm0
movq %rcx, (%rdi)
movups %xmm0, 8(%rdi)
retq
不幸的是,这种轻量级转换目前不是一种保证属性,只是一个实现细节。
您可以调整< code > do _ something _ using _ Foo 来接受一个泛型类型,并让< code>Foo和< code>u32实现一个特征:
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);
}
这在技术上是可能的 - 你可以随心所欲地向自己开枪。
如果您知道自己在做什么,可以使用std::mem::transmute。
但是,使用<code>transmute</code>和<code>Vec</code>是未定义的行为,因为未定义<code>Vec</code>的表示。相反,请参见Sven Marnach的答案。
另请参阅:
我需要这样的东西: 当然,我认为只有内置数字类型的向量才能传递给函数。 编译器告诉我,我需要为Vec提供FromIterator的trait trait
我在用org。乔达。时间LocalDate和LocalDateTime。我从外部源获得一个Unix时间戳,并希望从中生成一个LocalDate(时间)。关键是,在该外部系统的界面中定义,所有日期/时间都在UTC时区内。因此,我希望避免从该时间戳到本地系统的任何默认时区的任何隐式转换,这可能与UTC不同。有一个LocalDateTime的构造器用于这些事情,所以我尝试(作为一个例子): 结果让我有点
我有一个相机旋转矩阵3x3,然后我用罗德里格斯函数从旋转矩阵中得到旋转矢量,但是它给出的结果像,但是OpenGL函数需要度数。我认为是归一化的,我应该把每个元素乘以360来得到度数。但是OpenCV和OpenGL之间也有坐标系的差异。我如何在OpenGL坐标系中获得度数的旋转矢量?
问题内容: 我需要一个解决方案将String转换为字节数组,而无需像这样更改: 输入: 输出: 当我使用 那么回复是 但我希望回复是 问题答案: 您应始终确保序列化和反序列化使用相同的字符集,这会将字符映射到字节序列,反之亦然。默认情况下,String.getBytes()和新的String(bytes)使用默认字符集,该字符集可能是特定于语言环境的。 使用getBytes(Charset)重载
问题内容: 我有个问题。我正在尝试将一些字符串转换为日期,但我不知道日期到达的格式。 这或许让他们或等。 如何将这些字符串转换为Date?我尝试了这个: 但是,当我打印出someDate时,它的打印方式是这样的:2019-08-05 12:42:48.638 CEST这意味着,但是当我运行以上代码时,日期对象现在变成了,至少可以这样说。 有什么想法可以正确格式化日期格式吗? 问题答案: 你不能!
我有代码,工作完全按要求。但是,我们的企业构建服务器拒绝任何带有编译器警告的签入。 由于我没有使用await语句,因此(如预期的那样)对于带有操作to Func转换的操作构造函数显示了以下警告。 更新-建议答案#1 _operation=()=>new Task(operation.invoke); _rollback=()=>new Task(rollback.invoke); 更新-接受的答案