generics - 我可以在 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);
}
解决方案
推荐阅读
- javascript - Javascript切换工作但显示无样式菜单
- r - R在数据框的子集上应用函数
- javascript - 将“...”放在可滚动容器的末尾,但仅当滚动位于顶部时
- python - 查找具有给定长度的 String 的唯一子串
- gradle - 如何在 Gradle 中下载和引用单个工件?
- java - spring boot Kafka中如何多个消费者可以收听多个主题?
- java - ScrollPane javafx 自动滚动(将 vvalue 设置为 1.0)仅滚动到最后一项之前的项目
- php - 使用 nymber_format 使用 mysql 和 php 检索员工工资
- c# - ASP.NET 中是否有针对 ColumnHeaderMouseClick 的事件
- javascript - 使用 Ajax 成功结果更新全局变量