首页 > 解决方案 > 我可以在 Rust 中命名约束吗?

问题描述

我正试图围绕 Rust 中的泛型。为此,我决定在我创建的结构上通用地实现 Add。我注意到我不得不一遍又一遍地重复相同的约束。我还注意到我必须在我的代码中实现克隆,尽管 T 应该能够处理它,但那是因为我认为我还不知道在泛型中处理生命周期的正确方法。无论如何,我想命名 where 约束,这样我就不必在整个代码中复制/粘贴它们。

我可以给约束命名吗?

use std::cmp::PartialOrd;
use std::ops::Add;

struct Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone, // <-- I would like to give this a name
{
    item: T,
}

impl<T> Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone,
{
    pub fn new(item: T) -> Self {
        Self { item }
    }
}

impl<T> Add for Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone,
{
    type Output = Self;
    fn add(self, rhs: Thing<T>) -> Self {
        let left = self.item;
        let right = rhs.item;
        let result = left + right;
        Self::new(result)
    }
}

impl<'a, T> Add<&'a Thing<T>> for Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone,
{
    type Output = Thing<T>;

    fn add(self, rhs: &Thing<T>) -> Thing<T> {
        let left = self.item;
        let right = rhs.item.clone();
        let result = left + right;
        Thing::new(result)
    }
}

impl<'a, T> Add<Thing<T>> for &'a Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone,
{
    type Output = Thing<T>;

    fn add(self, rhs: Thing<T>) -> Thing<T> {
        let left = self.item.clone();
        let right = rhs.item;
        let result = left + right;
        Thing::new(result)
    }
}

impl<'a, 'b, T> Add<&'b Thing<T>> for &'a Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone,
{
    type Output = Thing<T>;

    fn add(self, rhs: &Thing<T>) -> Thing<T> {
        let left = self.item.clone();
        let right = rhs.item.clone();
        let result = left + right;
        Thing::new(result)
    }
}

fn main() {
    let foo = Thing::new(1);
    let bar = Thing::new(2);
    let baz = &foo + &bar;
    let biz = foo + &bar + baz;
    println!("{:?}", biz.item);
}

解决方案

布赖恩通过向我指出一个相关问题帮助我回答了我的问题。从那我想出了以下解决方案来命名我的特征界限。

use std::cmp::PartialOrd;
use std::ops::Add;

trait ICanAdd<T>: Add<Output = T> + PartialOrd + Clone {}
impl<T: Add<Output = T> + PartialOrd + Clone> ICanAdd<T> for T {}

struct Thing<T>
where
    T: ICanAdd<T>,
{
    item: T,
}

impl<T> Thing<T>
where
    T: ICanAdd<T>,
{
    pub fn new(item: T) -> Self {
        Self { item }
    }
}

impl<T> Add for Thing<T>
where
    T: ICanAdd<T>,
{
    type Output = Self;
    fn add(self, rhs: Thing<T>) -> Self {
        let left = self.item;
        let right = rhs.item;
        let result = left + right;
        Self::new(result)
    }
}

impl<'a, T> Add<&'a Thing<T>> for Thing<T>
where
    T: ICanAdd<T>,
{
    type Output = Thing<T>;

    fn add(self, rhs: &Thing<T>) -> Thing<T> {
        let left = self.item;
        let right = rhs.item.clone();
        let result = left + right;
        Thing::new(result)
    }
}

impl<'a, T> Add<Thing<T>> for &'a Thing<T>
where
    T: ICanAdd<T>,
{
    type Output = Thing<T>;

    fn add(self, rhs: Thing<T>) -> Thing<T> {
        let left = self.item.clone();
        let right = rhs.item;
        let result = left + right;
        Thing::new(result)
    }
}

impl<'a, 'b, T> Add<&'b Thing<T>> for &'a Thing<T>
where
    T: ICanAdd<T>,
{
    type Output = Thing<T>;

    fn add(self, rhs: &Thing<T>) -> Thing<T> {
        let left = self.item.clone();
        let right = rhs.item.clone();
        let result = left + right;
        Thing::new(result)
    }
}

fn main() {
    let foo = Thing::new(1);
    let bar = Thing::new(2);
    let baz = &foo + &bar;
    let biz = foo + &bar + baz;
    println!("{:?}", biz.item);
}

标签: genericsrustconstraints

解决方案


推荐阅读