struct Vec2<T: Sub<Output = T> + Add<Output = T> + Copy> {
x: T,
y: T
}
impl<T: Sub<Output = T> + Add<Output = T> + Copy> Add for Vec2<T> {
type Output = Vec2<T>;
fn add(self, rhs: Self) -> Self::Output {
Vec2 {
x: self.x + rhs.x,
y: self.y + rhs.y
}
}
}
Do I need to rewrite this not-so-beautiful <T: Sub<Output = T> + Add<Output = T> + Copy>
every time, or is there another, more elegant method that I am not familiar with?
I know one hack that can achive behaviour that I want by douing like so:
trait Numeric<T> : Sub<Output = T> + Add<Output = T> + Copy {}
macro_rules! add_impl {
($($t:ty)*) => ($(
impl Numeric<$t> for $t {}
)*)
}
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
#[derive(Debug)]
struct Vec2<T: Numeric<T>> {
x: T,
y: T
}
impl<T: Numeric<T>> Add for Vec2<T> {
type Output = Vec2<T>;
fn add(self, rhs: Self) -> Self::Output {
Vec2 {
x: self.x + rhs.x,
y: self.y + rhs.y
}
}
}
This, while partially solving my problem, looks even messier in my opinion.
And I know that "you shoud not put trait bounds in the struct definition", but i really want the compiler to give an error if the end user will try to:
let v = Vec2 {
x: "Hello", // ERROR WANTED HERE
y: "World"
};