gpt4 book ai didi

rust - 在带有 rust 的向量中实现特征的问题

转载 作者:行者123 更新时间:2023-12-03 11:38:51 26 4
gpt4 key购买 nike

我正在研究和试验使用rust 。
我想实现一个抽象的火车“GraphEntity”,然后再实现两个特征“Point”和“Triangle”。
我有以下代码可以正常工作:

use std::cmp::Ordering;

trait GraphEntity {
fn plot (&self) {
println!("this is a plot!");
}
}

#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}

impl Ord for Point {
fn cmp(&self, other: &Self) -> Ordering {
(self.x, &self.y).cmp(&(other.x, &other.y))
}
}

impl PartialOrd for Point {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl PartialEq for Point {
fn eq(&self, other: &Self) -> bool {
(self.x, &self.y) == (other.x, &other.y)
}
}

impl Eq for Point { }


#[derive(Debug)]
struct Triangle {
x: i32,
y: i32,
z: i32,
}


impl GraphEntity for Point {
fn plot (&self) {
println!("P:[{},{}]", self.x, self.y);
}

}

impl GraphEntity for Triangle {
fn plot (&self) {
println!("T:[{},{},{}]", self.x, self.y,self.z);
}

}

struct SetOfEntities {
list: Vec<Box<dyn GraphEntity>>,
}

impl SetOfEntities {
fn new () -> Self {
Self {
list: Vec::new(),
}
}

fn append<S: GraphEntity + 'static>(&mut self, entity: S) -> &mut Self {
self.list.push(Box::new(entity));

self
}

fn plot(self) {
for x in self.list {
x.plot();
}
}
}


fn main() {

let p1: Point = Point { x: 1, y: 0 };
let p2: Point = Point { x: -1, y: 2 };
let t: Triangle = Triangle { x: 1, y: 2, z: 3};

let mut set = SetOfEntities::new();
set.append(p1);
set.append(p2);
set.append(t);
set.plot();
}
我现在想更改附加功能并检查列表中是否已存在任何现有点。
如果它已经存在,我不会添加到列表中。
fn append<S: GraphEntity + 'static>(&mut self, entity: S) -> &mut Self {
match self.list.binary_search(&entity) {
Ok(pos) => self,
Err(pos) => { self.list.push(Box::new(entity)); self },
}
}
这给了我以下错误:
error[E0308]: mismatched types
--> src/main.rs:70:39
|
69 | fn append<S: GraphEntity + 'static>(&mut self, entity: S) -> &mut Self {
| - this type parameter
70 | match self.list.binary_search(&entity) {
| ^^^^^^^ expected struct `std::boxed::Box`, found type parameter `S`
|
= note: expected reference `&std::boxed::Box<dyn GraphEntity>`
found reference `&S`

error[E0277]: the trait bound `dyn GraphEntity: std::cmp::Ord` is not satisfied
--> src/main.rs:70:39
|
70 | match self.list.binary_search(&entity) {
| ^^^^^^^ the trait `std::cmp::Ord` is not implemented for `dyn GraphEntity`
|
= note: required because of the requirements on the impl of `std::cmp::Ord` for `std::boxed::Box<dyn GraphEntity>`
知道如何纠正这个问题吗?

最佳答案

试图修复错误
你有两个错误:

  • 第一个问题很容易解决:expected struct 'std::boxed::Box', found type parameter 'S' . binary_search函数从 self.list 开始需要一个框是 Vec的盒子。您可以将其更改为 self.list.binary_search(&Box::new(entity)) . (您可能仍然需要帮助编译器将其强制为 dyn 类型。)
  • 第二个错误有点棘手,很难解决。问题是 binary_search需要实现 Ord 的对象trait,但它只知道 GraphEntity因为对象的类型是dyn GraphEntity .
    对于大多数特征,您可以给出 GraphEntity一个 super 特征,这将被修复,但不幸的是,这在这里不起作用,因为您无法为 Ord 创建特征对象.你会得到错误 E0038 ,因为这可能不安全。
    我的小修复想法是创建一个 cmp GraphEntity中的函数并使用 binary_search_by而不是 binary_search .然而cmp会有 Self参数,这会导致相同的错误。据我所知,你无法按照你想要的方式修复它。

  • 如果您无法在 Rust 中修复您的代码,那么代码的逻辑通常会出现问题。我认为这里就是这种情况,因为对于 binary_search你需要比较 dyn GraphEntity对象。所以你还想比较 PointTriangle ,它们没有(部分)顺序关系。
    使用枚举
    您可能会注意到,Rust 的动态调度不是为(某些)复杂情况而设计的。比较不同类型的对象并非易事。实现相同的特征并没有说明比较它们。
    如果 binary_search超过 GraphEntity objects 正是您想要的,而不是最好的解决方案可能是使用枚举。 Rust 将确保您处理比较不同类型的每种情况。
    比较函数可能如下所示:
    fn cmp(&self, other: &GraphEntity) -> Ordering {
    match (self,other) {
    (GraphEntity::Point(p1),GraphEntity::Point(p2))
    => (p1.x, p1.y).cmp(&(p2.x, p2.y)),
    (GraphEntity::Triangle(t1),GraphEntity::Triangle(t2))
    => (t1.x, t1.y, t1.z).cmp(&(t2.x, t2.y, t2.z)),
    (GraphEntity::Point(_),GraphEntity::Triangle(_))
    => Ordering::Less,
    (GraphEntity::Triangle(_),GraphEntity::Point(_))
    => Ordering::Greater,
    }
    }
    如果 GraphEntity 中有更多变体,这会变得非常复杂。枚举,但它可以处理复杂性。而动态调度在处理模块化方面更好。
    似乎您试图将您的程序建模为使用基于继承的 OOP 语言(如 Java 或 C++)。小心,这是很多 Rust 初学者都会犯的错误,包括我自己。

    关于rust - 在带有 rust 的向量中实现特征的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64169075/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com