#Trait objects with subtraits

7 messages · Page 1 of 1 (latest)

hot cloud
#

The code below should be pretty self-explanatory: a Scalar is a plain old number, and Scalar.exp should return another Scalar, possibly of a different type than the Scalar it was called on.

pub trait Scalar:
    ToString +
    Add + AddAssign +
    Sub + SubAssign +
    Mul + MulAssign +
    Div + DivAssign +
    Neg + Rem +
    PartialEq + PartialOrd
{
    fn exp(&self) -> Box<dyn Scalar>;
}

This doesn't work, since one of the subtraits of Scalar requires Sized, and thus Scalar can't be a trait object.

How should I do what I'm trying to do here? I need a trait object that guarantees the subtraits listed above, but I don't think I can make one directly.

round forge
#

you cannot ever have a trait object which implements PartialEq or PartialOrd, because those operations require two values of the same type

#

You will have to find a different solution. For example, perhaps you could define an enum Scalar instead of using trait objects. (This will be much more efficient if it works)

storm hollow
#

You could also define a dyn-safe variant of those traits, but you'll need to decide what it means to compare two scalars of different types.

#

For reference

trait Scalar : DynPartialEq + ... 
``````rs
trait DynPartialEq: Any {
  fn dyn_eq(&self, other: &dyn DynPartialEq) -> bool;
}
``````rs
//Assuming `SomeScalar` already implements `PartialEq`
impl DynPartialEq for SomeScalar {
  fn dyn_eq(&self, other: &dyn DynPartialEq) -> bool{
    let Some(other) = other.downcast_ref<Self>() else { return false };
    other == self
  }
}
```Here I'm borrowing a convention from Java and assuming that comparing two things of different types yields `false`.
#

A more interesting question is ordering.

#

You also may want to not make another trait, and instead just define dyn_eq on Scalar directly.