Add only generic types that have different concrete types

Viewed 52

Given Base<Foo> and Base<Bar>, is there a way to implement Add such that only Base<Foo> + Base<Bar> and Base<Bar> + Base<Foo> compile? ie. only add if the concrete types are different?

In my case they can be only 2 different types.

Example:

Given

#[derive(Debug)]
struct Base<T> {
    n: u32,
    _marker: std::marker::PhantomData<T>,
}

trait FooTrait {}
struct FooImpl;
impl FooTrait for FooImpl {}

trait BarTrait {}
struct BarImpl;
impl BarTrait for BarImpl {}

is there a way to implement Add such that

let foo: Base<Foo> = Base::new();
let foo2 = foo.clone();
let bar: Base<Bar> = Base::new();
let bar2: bar.clone();

let foobar = foo + bar;
let foobar = bar2 + foo2;

compiles but

let foo: Base<Foo> = Base::new();
let foo2 = foo.clone();
let bar: Base<Bar> = Base::new();
let bar2: bar.clone();

let foofoo = foo + foo2;
let barbar = bar + bar2;

does not?

I tried

impl<A, B> Add<Base<B>> for Base<A>
where
    A: DerivedATrait,
    B: DerivedBTrait,
{
    type Output = Base<A>;

    fn add(self, rhs: Base<B>) -> Base<A> {
        Base::new(self.n + rhs.n)
    }
}

but it only allows Base<A> + Base<B>, not the other way around, and an additional Add implementation swapping the bounds does not compile.

0 Answers
Related