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
相关产品推荐
相关产品推荐

