简体   繁体   English

如何解决特征的一般实现(一揽子实现)的冲突?

[英]How to work around conflicts of generic implementations of traits (blanket implementations)?

I'm coming from C++ and I'm running into issues with generic trait implemntations. 我来自C ++,我遇到了泛型特征实现的问题。

I'm trying to build a geometry library that does some operation on both polygons and open paths, but behaves slightly different for each case. 我正在尝试构建一个在多边形和开放路径上执行某些操作的几何库,但每种情况的行为略有不同。 Ideally I want one implementation of a geometry operation as a method which can query the object it's operating on for a flag. 理想情况下,我想要一个几何操作的实现作为一种方法,可以查询它正在操作的对象的标志。

I also want this library to work on any object that can look like a polygon or open path, not just my data types, so I want traits for PolygonLike and OpenPathLike that can be implemented on any type. 我也希望这个库可以处理任何看起来像多边形或开放路径的对象,而不仅仅是我的数据类型,所以我想要可以在任何类型上实现的PolygonLikeOpenPathLike特性。 I have code that looks like this: 我的代码看起来像这样:

trait Clipable {
    fn closed() -> bool;
    fn geom_func(&self) {
        if Self::closed() {
            println!("closed");
        } else {
            println!("open");
        }
    }
}

trait PolygonLike {}
trait OpenPathLike {}

struct Point(f64, f64);
type PointVec = Vec<Point>;
struct Poly(PointVec);
struct Path(PointVec);

impl PolygonLike for Poly {}
impl OpenPathLike for PointVec {}

impl<T> Clipable for T
where
    T: PolygonLike,
{
    fn closed() -> bool {
        true
    }
}

impl<T> Clipable for T
where
    T: OpenPathLike,
{
    fn closed() -> bool {
        false
    }
}

fn main() {
    let pg = Poly(PointVec::new());
    let op = Path(PointVec::new());
    pg.geom_func();
    op.geom_func();
}

The code fails to compile with: 代码无法编译:

error[E0119]: conflicting implementations of trait `Clipable`:
  --> src/main.rs:28:1
   |
24 | impl<T> Clipable for T where T: PolygonLike {
   | ------------------------------------------- first implementation here
...
28 | impl<T> Clipable for T where T: OpenPathLike {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

I have read elsewhere that the where clause isn't used by the conflict checker, even though no type implements both PolygonLike and OpenPathLike . 我在其他地方读过冲突检查器没有使用where子句,即使没有类型同时实现PolygonLikeOpenPathLike

I get that this is because a consumer could just implement both those traits and break the library. 我知道这是因为消费者可以实现这两个特征并破坏库。 What I don't get is how I can work around this. 我没有得到的是我如何解决这个问题。

I have seen other posts where people have used newtypes to limit generic implementations, but I can't figure out how to make that work for my scenario. 我看过其他帖子,其中人们使用newtypes来限制泛型实现,但我无法弄清楚如何使我的方案工作。

This is currently not possible. 目前这是不可能的。 You will need to implement Clipable for Poly , PointVec , and any others, individually. 您需要ClipablePolyPointVec和任何其他人实现Clipable

You might consider writing macros to make this less repetitive: 您可以考虑编写宏来减少重复性:

macro_rules! clipable_poly {
    ($($ty: ty),+) => {
        $(
            impl PolygonLike for $ty {}

            impl Clipable for $ty {
                fn closed() -> bool {
                    true
                }
            }
        )+
    }   
}

macro_rules! clipable_open {
    ($($ty: ty),+) => {
        $(
            impl OpenPathLike for $ty {}

            impl Clipable for $ty {
                fn closed() -> bool {
                    false
                }
            }
        )+
    }   
}

clipable_poly!(Poly, Point);
clipable_open!(PointVec, Path);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM