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



我来自C++,遇到了通用特征实现的问题。

我正在尝试构建一个几何体库,它对多边形和开放路径都进行一些操作,但在每种情况下的行为略有不同。理想情况下,我想要一个几何运算的实现作为一种方法,它可以查询它正在操作的对象以获取标志。

我还希望这个库能处理任何看起来像多边形或开放路径的对象,而不仅仅是我的数据类型,所以我希望PolygonLikeOpenPathLike的特征可以在任何类型上实现。我有这样的代码:

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();
}

代码无法使用进行编译

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

我在其他地方读到,冲突检查器不使用where子句,即使没有类型同时实现PolygonLikeOpenPathLike

我明白这是因为消费者可以同时实现这两个特性并破坏库。我不知道如何解决这个问题。

我在其他帖子中看到过人们使用新类型来限制通用实现,但我不知道如何使其适用于我的场景。

这目前是不可能的。您需要分别为PolyPointVec和任何其他对象实现Clipable

您可以考虑编写宏来减少重复:

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);

最新更新