You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中可以为泛型where约束条件命名以避免重复编写吗?

问题

在学习掌握Rust的泛型特性时,尝试为自定义结构体泛型实现Add trait,过程中发现需要反复编写完全相同的where约束条件,还遇到了需要额外调用clone的问题(推测是目前还未掌握泛型生命周期的正确用法导致)。希望可以为重复的where约束条件命名,避免在代码中反复复制粘贴相同的约束内容。

示例代码如下:

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

struct Thing<T>
where
    T: Add<Output = T> + PartialOrd + Clone, // <-- 我希望给这个约束命名
{
    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);
}
解决方案

可通过自定义trait合并多个约束的方式实现约束复用,实现代码如下:

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

内容的提问来源于stack exchange,提问作者mpls

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:36:04