- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个应该实现基本数学运算符的简单结构。最初我不想让这些消耗操作数,所以我实现了引用的特征,例如 Add
。 :
impl<'a, 'b> Add<&'b MyType> for &'a MyType {
type Output = MyType;
fn add(self, rhs: &'b MyType) -> Self::Output {
// Implementation...
}
}
这让我可以:
let result = &v1 + &v2;
在哪里v1
和 v2
类型为 MyType
.
然后我意识到有时候使用操作数在句法上更方便,例如:
let result = &v1 + &v2 + &v3;
因为有一个中间结果,上面的代码无法编译,你必须这样做:
let result = &v1 + &(&v2 + &v3);
所以我最终实现了移动和借用的其他排列,它们只是服从第一个排列:
impl<'a> Add<&'a MyType> for MyType {
type Output = MyType;
fn add(self, rhs: &'a MyType) -> Self::Output {
&self + rhs
}
}
impl<'a> Add<MyType> for &'a MyType {
type Output = MyType;
fn add(self, rhs: MyType) -> Self::Output {
self + &rhs
}
}
impl Add<MyType> for MyType {
type Output = MyType;
fn add(self, rhs: MyType) -> Self::Output {
&self + &rhs
}
}
这可行,但很麻烦。
我在寻找更简单的方法,例如使用 Borrow<T>
:
impl<B> Add<B> for B
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
// Implementation...
}
}
但是由于 type parameter
的缘故,这无法编译,这是可以理解的。 B must be used as the type parameter for some local type
.
是否有任何其他技巧可以避免 Add
的所有这些样板实现?/Sub
/Mul
/Div
等等?
更新:
@EvilTak 在评论中提出了一个建议,通过实现 B: Borrow<MyType>
来减少样板组合。 MyType
上的版本和 &MyType
明确地。这是一个很好的改进:
impl<'a, B> Add<B> for &'a MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
// Implementation...
}
}
impl<B> Add<B> for MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
&self + rhs
}
}
最佳答案
进入这个兔子洞后,我将回答我自己的问题。
我开始使用 Borrow 来减少我需要实现的函数数量:
impl<'a, B> Add<B> for &'a MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
// Implementation...
}
}
impl<B> Add<B> for MyType
where
B: Borrow<MyType>,
{
type Output = MyType;
fn add(self, rhs: B) -> Self::Output {
&self + rhs
}
}
这很有效,直到我还需要添加 MyType
和 MyOtherType
在一起。
尝试使用 Borrow<T>
来实现它给出错误 conflicting implementations of trait
:
impl<'a, B> Mul<B> for &'a MyType
where
B: Borrow<MyOtherType>,
{
type Output = MyOtherType;
fn mul(self, rhs: B) -> Self::Output {
/// Implementation...
}
}
这是因为类型 could theoretically implement both Borrow<MyType>
和 Borrow<MyOtherType>
同时,编译器不知道要使用哪个实现。
那时我决定改为尝试宏路线。如您所料,this has been done before by others .
几个不同的地方建议使用 impl_ops ,此后已被 auto_ops 取代.
这个 crate 允许您通过执行以下操作为运算符定义所有各种组合:
impl_op_ex!(+ |a: &DonkeyKong, b: &DonkeyKong| -> DonkeyKong { DonkeyKong::new(a.bananas + b.bananas) });
但是,这个箱子有不能使用泛型的限制。就我而言 MyType
实际上是 Matrix<const M: usize, const N: usize>
,所以我需要泛型支持。
然后我遇到了 auto_impl_ops , 它可以让你从一个 AddAsign
生成所有不同的加法组合特征实现(和其他操作一样),并且还支持泛型。
use std::ops::*;
#
# #[derive(Clone, Default)]
# struct A<T>(T);
#[auto_impl_ops::auto_ops]
impl<M> AddAssign<&A<M>> for A<M>
where
for<'x> &'x M: Add<Output = M>,
{
fn add_assign(&mut self, other: &Self) {
self.0 = &self.0 + &other.0;
}
}
此处的一个限制是结果必须始终与 Self
的类型相同,如果您正在执行矩阵乘以向量等操作,情况可能并非如此。
另一个可能的问题是,对于二元运算符, crate 将在使用您的赋值运算符实现之前克隆左侧的值,并返回克隆。对于矩阵乘法,我还必须克隆 self
在MulAssign
实现,否则我将覆盖我仍在用于矩阵乘法的数据。这意味着这里至少有一个冗余内存副本,如果我手动实现运算符,我将不会有。
我现在已经使用了这个库。如果情况发生变化,我会尝试在此处进行更新。
关于rust - 为移动和借用的所有组合实现 Add、Sub、Mul、Div,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74363718/
我正在使用 tcod-rs。用于绘制到 RootConsole 的每个方法都采用一个可变引用。中央循环是一个 while 循环,它等待窗口关闭、清除屏幕、绘制,然后刷新。 “检查窗口关闭”方法也采用可
This question already has answers here: How to return a reference to a sub-value of a value that is
我是新手,我已经阅读了有关所有权和借用的文档。显然,我开始为这个概念而苦苦挣扎... 这是我的代码: #[derive(Serialize, Deserialize, Debug)] pub stru
我在借阅检查器上遇到了问题。我有一个特征(Physics),它具有getters(例如velocity)和setters(例如velocity_mut)。它还具有使用getter和setter的默认方
我正在用 Rust 编写 Rogue-like。我有一个 Player,它有一个 Vec 的盒装 TimedEffects。定时效果有一个 activate(&mut Player) 和 deacti
我觉得 rc::Weak可以使用(某种)AsRef特征实现。我试图从弱指针借用一些共享内容,但这不会编译: use std::rc::Weak; struct Thing(Weak); impl Th
我正在学习Rust。对于我的第一个程序,我编写了以下代码来维护有关部分排序的数据: use std::collections::{HashMap, HashSet}; struct Node {
这个问题在这里已经有了答案: Cannot borrow as immutable because it is also borrowed as mutable in function argume
在尝试实现一个迭代器以产生对链表元素的可变引用时,我偶然发现了一个奇怪的问题。 这很好用: impl Iterator for LinkedListIterator{ fn next(&mut
我有this minimal example code : use std::borrow::BorrowMut; trait Foo {} struct Bar; impl Foo for Bar
struct State { x: i32 } trait A { fn a(&mut self, b: &i32); } impl A for State { fn a(&m
我有一个 Element 结构,它实现了一个更新方法,该方法需要一个滴答持续时间。该结构包含一个组件向量。允许这些组件在更新时修改元素。我在这里遇到借用错误,我不确定该怎么做。我尝试用 block 修
我正在尝试做这样的事情 use std::cell::{RefCell,Ref,RefMut}; use std::rc::Rc; struct Entity; struct Tile { e
我已连接到 Deribit websocket 以获取选项数据,但以下代码片段仅获得一个有效的数据响应,然后停止更新,但表示它仍在运行。 该网站建议使用 asyncio 模块,但能够使用以下代码片段提
我是一名优秀的程序员,十分优秀!