假设存在以下功能:
fn merge(a1: A, a2: A) -> A { /* implemented */ }
有没有办法使用盒装类型为同一操作编写函数?那就是:
fn boxed_merge(a1: Box<A>, a2: Box<A>) -> Box<A> { /* ??? */ }
答案 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);
}
值得注意的是,在盒装情况下这会更有效,因为您不必执行任何其他分配。
这仅适用于
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))
}