Как обойти конфликты общих реализаций черт (общих реализаций)? - PullRequest
0 голосов
/ 10 января 2019

Я пришел из C ++, и у меня возникли проблемы с реализациями универсальных признаков.

Я пытаюсь создать библиотеку геометрии, которая выполняет некоторые операции как с полигонами, так и с открытыми путями, но ведет себя немного по-разному для каждого случая. В идеале мне нужна одна реализация геометрической операции в качестве метода, который может запрашивать у флага объект, над которым он работает,

Я также хочу, чтобы эта библиотека работала с любым объектом, который может выглядеть как многоугольник или открытый путь, а не только с моими типами данных, поэтому я хочу иметь признаки для PolygonLike и OpenPathLike, которые могут быть реализованы для любого типа. У меня есть код, который выглядит так:

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 не используется средством проверки конфликтов, хотя ни один тип не реализует как PolygonLike, так и OpenPathLike.

Я понял, что это потому, что потребитель мог просто реализовать обе эти черты и сломать библиотеку. Чего я не понимаю, так это как обойти это.

Я видел другие посты, где люди использовали новые типы для ограничения общих реализаций, но я не могу понять, как заставить это работать для моего сценария.

1 Ответ

0 голосов
/ 10 января 2019

В настоящее время это невозможно. Вам нужно будет реализовать Clipable для Poly, PointVec и любые другие, индивидуально.

Вы можете написать макросы, чтобы сделать это менее повторяющимся:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...