I have some struct(s) that don't implement copy, e.g:
#[derive(Clone)]
struct My { val: f64 }
This struct implements all of the 4 mathematical crosses with itself, and in every case returns an owned My, i.e. Output = My.
impl Add<My> for My {...}; impl Add<My> for &My {...};
impl Add<&My> for My {...}; impl Add<&My> for &My {...};
I am trying to design a generic blanket trait such that I could define an operation like:
fn op<T: CrossAdd>(re: &T, owned: T) -> T {
// contains all 4 crosses
(re + ((re + re) + re)) + owned
}
But, I can't do it.
I have come close with help from @quinedot, who suggested the following:
trait ArithRef
where
Self: Sized,
Self: Add<Self, Output = Self::Owned> + Add<Self::Owned, Output = Self::Owned>,
{
type Owned: Sized +
Add<Self, Output = Self::Owned> + Add<Self::Owned, Output = Self::Owned>;
}
impl<T, Owned> ArithRef for T
where
T: Add<T, Output = Owned> + Add<Owned, Output = Owned>,
Owned: Add<T, Output = Owned> + Add<Owned, Output = Owned>,
{
type Owned = Owned;
}
which allows one to write:
fn some_op<RefT: ArithRef>(re: RefT, re2: RefT) -> RefT::Owned
{
// clones are just clones of references
(re.clone() + ((re.clone() + re.clone()) + re)) + re2
}
I have another solution which avoids blanket implementation and directly adds traits to my types but that has other issues.
Am I trying to do something that fundamentally won't work? Or I just haven't discovered some appropriate solution yet?