从一个Vec移动包装的值到另一个Vec。

huangapple go评论64阅读模式
英文:

Move boxed values from one Vec to another

问题

I'd like to move some Boxed values from one Vec to another, but I can't figure out if this is possible or whether I'm thinking about it wrong.

So far, my smallest example of the problem is:

#[derive(Debug)]
pub struct B {
    value: usize
}

fn main() {
    let v1: Vec<_> = (1..3).map(|i| Box::new(B { value: i })).collect();
    let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
    println!("{v2:?}");
}

Which gives the error:

error[E0507]: cannot move out of `*b` which is behind a shared reference
 --&gt; src/main.rs:8:45
  |
8 |     let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
  |                                             ^^ move occurs because `*b` has type `Box<B>`, which does not implement the `Copy` trait

I've tried various (but possibly incorrect) methods of trying to move the contents of the Box with std::mem::swap and friends, but haven't managed to get that right.

For clarity, I want to avoid copying the Bs - in reality they are large. I haven't experimented with an Rc, and ideally I'd avoid that. v1 is effectively consumed when it is mapped into v2.

As shown above, the example is pretty uninteresting, in the "real" case, v1 is a Vec of 2-tuples, and I'd like to map it to a Vec of 3-tuples with an extra element derived from the first two.

I'm aware I don't need all the type annotation, but that helps check I'm getting what I want. For a while I thought I had succeeded, but was actually getting a Vec<&Box<B>> (or similar, don't take my exact word for it).

Does anyone have any insight as to how to do this, or how I can approach the problem differently? Thanks!

英文:

I'd like to move some Boxed values from one Vec to another, but I can't figure out if this is possible or whether I'm thinking about it wrong.

So far, my smallest example of the problem is:

#[derive(Debug)]
pub struct B {
    value:      usize
}

fn main() {
    let v1: Vec&lt;_&gt; = (1..3).map(|i| Box::new(B{ value: i})).collect();
    let v2: Vec&lt;Box&lt;B&gt;&gt; = v1.iter().map(|b| *b).collect();
    println!(&quot;{v2:?}&quot;);
}

Which gives the error:

error[E0507]: cannot move out of `*b` which is behind a shared reference
 --&gt; src/main.rs:8:45
  |
8 |     let v2: Vec&lt;Box&lt;B&gt;&gt; = v1.iter().map(|b| *b).collect();
  |                                             ^^ move occurs because `*b` has type `Box&lt;B&gt;`, which does not implement the `Copy` trait

I've tried various (but possibly incorrect) methods of trying to move the contents of the Box with std::mem::swap and friends, but haven't managed to get that right.

For clarity, I want to avoid copying the B's - in reality they are large. I haven't experimented with an Rc, and ideally I'd avoid that. v1 is effectively consumed when it is mapped into v2.

As shown above, the example is pretty uninteresting, in the "real" case, v1 is a Vec of 2-tuples, and I'd like to map it to a Vec of 3-tuples with an extra element derived from the first two.

I'm aware I don't need all the type annotation, but that helps check I'm getting what I want. For a while I thought I had succeeded, but was actually getting a Vec&lt;&amp;Box&lt;B&gt;&gt; (or similar, don't take my exact word for it).

Does anyone have any insight as to how to do this, or how I can approach the problem differently? Thanks!

答案1

得分: 3

如果您想 消耗 原始向量,您应该使用 into_iter 而不是 iter,后者只提供共享引用:

let v1: Vec<_> = (1..3).map(|i| Box::new(B{ value: i})).collect();
let v2: Vec<Box<B>> = v1.into_iter().collect();
英文:

If you want to consume the orginial vector you want into_iter not iter which only gives you shared references:

let v1: Vec&lt;_&gt; = (1..3).map(|i| Box::new(B{ value: i})).collect();
let v2: Vec&lt;Box&lt;B&gt;&gt; = v1.into_iter().collect();

huangapple
  • 本文由 发表于 2023年4月6日 19:34:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75949043.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定