在Rust中设计返回不可复制结构的函数API

vsaztqbk  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(112)

我正在尝试编写对图形进行操作的函数,如下所示:

#[derive(Hash, Eq, PartialEq, Copy, Clone)]
struct Node(usize);

#[derive(Clone)]
struct Graph {
    edges: HashMap<Node, HashMap<Node, usize>>
}

我的函数之一就是用某种方式合并两个图形。所以目前,函数声明和实现看起来像:

fn combine(Graph a, Graph b) -> Graph {
    Graph::new(...)
}

impl BitOr for Graph {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self::Output {
        combine(self, rhs)
    }
}

预期结果是编译以下代码:

// Define A, B, C, D
let A = Graph { edges: [].into() };
let B = Graph { edges: [].into() };
let C = Graph { edges: [].into() };
let D = Graph { edges: [].into() };

let new_graph1 = A | B | C;
let new_graph1 = A | B | D;

然而,由于我的Graph是不可复制的,这意味着每次我调用函数时,用户都必须执行A.clone()|B.克隆()|C.克隆()|D.clone()“,这是不理想的。
combine不能返回一个引用,因为它不能创建一个新的Graph然后返回一个引用,所以它返回一个Graph。

impl BitOr for &Graph {
    type Output = Self;

    fn bitor(self, rhs: Self) -> Self::Output {
        combine(self, rhs)
    }
}

// ...

// A = ...
// B = ...
// C = ...
D = &A | &B | &C

由于(&A | &B)Graph,因此将出现错误。
有人有什么建议吗?我是Rust的新手,所以我可能错过了一些东西,但我已经尝试了相当长的一段时间,要么我遇到了返回引用(明显的生存期问题),要么逐位操作停止工作,这对我的用例非常重要。

w8rqjzmb

w8rqjzmb1#

可以对引用和拥有值的所有组合实现BitOr,在combine()中采用更容易/更高性能的方法。例如,使用combine()获取引用:

impl BitOr for Graph {
    type Output = Graph;
    fn bitor(self, other: Graph) -> Graph { combine(&self, &other) }
}
impl BitOr for &'_ Graph {
    type Output = Graph;
    fn bitor(self, other: &Graph) -> Graph { combine(self, other) }
}
impl BitOr<&'_ Graph> for Graph {
    type Output = Graph;
    fn bitor(self, other: &Graph) -> Graph { combine(&self, other) }
}
impl BitOr<Graph> for &'_ Graph {
    type Output = Graph;
    fn bitor(self, other: Graph) -> Graph { combine(self, &other) }
}

现在用户可以使用任何最舒适的东西,并可以链接:例如,&A | &B | &C将工作。

相关问题