繁体   English   中英

如果我在 struct 块中定义了 Rust 代码中的每个 impl 块,是否需要手动重写它的所有特征边界?

[英]Do I need to manually rewrite all the trait bounds for every impl block in my Rust code if I defined it in struct block?

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
        }
    }
}

我是否需要每次都重写这个不太漂亮的<T: Sub<Output = T> + Add<Output = T> + Copy> ,还是有另一种我不熟悉的更优雅的方法?

我知道一种hack可以通过这样做来实现我想要的行为:

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
        }
    }
}

这虽然部分解决了我的问题,但在我看来看起来更加混乱。

而且我知道“ 你不应该在结构定义中放置特征边界”,但我真的希望编译器在最终用户尝试时给出错误:

let v = Vec2 {
        x: "Hello", // ERROR WANTED HERE
        y: "World"
    };

特征别名是不稳定的,但如果您使用夜间工具链,您可以将您的长特征边界别名为较短的,以便在您的impl块中实际指定:

#![feature(trait_alias)]

use core::ops::{Add, Sub};

trait Numeric<T> = Sub<Output = T> + Add<Output = T> + Copy;

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
        }
    }
}

实现第二种方法的一种更正常的方法是只为满足特征绑定的所有类型impl Numeric ,这消除了对宏的需要:

impl<T> Numeric<T> for T where T: Sub<Output = T> + Add<Output = T> + Copy {}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM