合并盒装元素

时间:2017-05-17 07:33:50

标签: rust

假设存在以下功能:

fn merge(a1: A, a2: A) -> A { /* implemented */ }

有没有办法使用盒装类型为同一操作编写函数?那就是:

fn boxed_merge(a1: Box<A>, a2: Box<A>) -> Box<A> { /* ??? */ }

3 个答案:

答案 0 :(得分:4)

我会提倡按值merge 作为您的基本实现。相反,变异方法提供了更大的灵活性。然后,您可以使用by-value和by-boxed-value方法构建它:

struct A(u8);

impl A {
    fn merge_ref(&mut self, other: &A) {
        self.0 += other.0
    }
}

fn merge(mut a1: A, a2: A) -> A { 
    a1.merge_ref(&a2);
    a1
}

fn boxed_merge(mut a1: Box<A>, a2: Box<A>) -> Box<A> {
    a1.merge_ref(&a2);
    a1
}

fn main() {
    let a1 = A(1);
    let a2 = A(2);

    let a3 = merge(a1, a2);

    let boxed_a3 = Box::new(a3);
    let boxed_a4 = Box::new(A(4));

    let boxed_a7 = boxed_merge(boxed_a3, boxed_a4);

    println!("{}", boxed_a7.0);
}

值得注意的是,在盒装情况下这会更有效,因为您不必执行任何其他分配。

As oli_obk - ker points out

  

这仅适用于Copy结构的合并。如果您有两个合并的集合,则该集合的元素可能不是可复制的

可以通过将事物合并到merge_ref中的值并使用相同的技巧在boxed_merge方法中开箱即用来解决这个问题:

struct B(Vec<u8>);

impl B {
    fn merge_ref(&mut self, other: B) {
        self.0.extend(other.0)
    }
}

fn merge(mut b1: B, b2: B) -> B { 
    b1.merge_ref(b2);
    b1
}

fn boxed_merge(mut b1: Box<B>, b2: Box<B>) -> Box<B> {
    b1.merge_ref(*b2);
    b1
}

fn main() {
    let b1 = B(vec![1]);
    let b2 = B(vec![2]);

    let b3 = merge(b1, b2);

    let boxed_b3 = Box::new(b3);
    let boxed_b4 = Box::new(B(vec![4]));

    let boxed_b7 = boxed_merge(boxed_b3, boxed_b4);

    println!("{:?}", boxed_b7.0);
}

我们仍然没有额外的分配。

答案 1 :(得分:3)

您可以通过取消引用它们来访问盒装参数的内容,并将它们组合在一个新的Box中。例如:

fn merge(a1: Box<usize>, a2: Box<usize>) -> Box<usize> {
    Box::new(*a1 + *a2)
}

fn main() {
    let a1 = Box::new(1);
    let a2 = Box::new(2);

    println!("{}", merge(a1, a2));
}

答案 2 :(得分:3)

您可以通过取消引用merge功能中的框来重复使用boxed_merge功能。请注意,这不会重复使用分配,而是创建一个新分配

fn boxed_merge(a1: Box<A>, a2: Box<A>) -> Box<A> {
    Box::new(merge(*a1, *a2))
}