不久前,我考虑为斐波那契数列编写一个通用迭代器,它既可以接受原始数字,也可以接受自定义类型(例如
bignums)。在无法获得适用于原始类型和 的版本后bignums,我偶然发现了这个问题:
其中使用所谓的高排名特征边界来解决这个特定问题的问题。
但是,现在我正在尝试使用类似的策略来使用*_assign
运算符。特别是,我正在尝试获得与此类似的工作:
use std::ops::{Add, AddAssign};
fn add_test<'a, T>(x: &'a T, y: &'a T) -> T
where
for<'b> &'b T: Add<Output = T>,
{
x + y
}
fn add_assign_test<'a, T>(x: &'a mut T, y: &'a T) -> T
where
for<'b> &'b mut T: AddAssign<&'b T>,
T: Clone,
{
x += y;
x.clone()
}
fn main() {
println!("add_test()={}", add_test(&1, &2));
println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
}
Run Code Online (Sandbox Code Playgroud)
add_test()按预期工作,但我无法以add_assign_test()类似的方式工作。我收到的错误表明,对于原始类型的这种行为,实际上可能不存在实现:
use std::ops::{Add, AddAssign};
fn add_test<'a, T>(x: &'a T, y: &'a T) -> T
where
for<'b> &'b T: Add<Output = T>,
{
x + y
}
fn add_assign_test<'a, T>(x: &'a mut T, y: &'a T) -> T
where
for<'b> &'b mut T: AddAssign<&'b T>,
T: Clone,
{
x += y;
x.clone()
}
fn main() {
println!("add_test()={}", add_test(&1, &2));
println!("add_assign_test()={}", add_assign_test(&mut 2, &2));
}
Run Code Online (Sandbox Code Playgroud)
我可以创建一个宏来为这些运算符创建实现,这些运算符实际上引用原始类型,但这似乎有点浪费。有没有其他方法可以达到同样的效果?
只是代码中的一个小疏忽。我们来看看特质:
pub trait AddAssign<Rhs = Self> {
fn add_assign(&mut self, rhs: Rhs);
}
Run Code Online (Sandbox Code Playgroud)
该方法的接收者是已经&mut self而不是self。您必须做额外工作的原因Add是因为它接受self作为接收者。这AddAssign意味着:如果一个类型T实现了,您可以调用!上的AddAssign方法。add_assign()&mut T
因此,不要写:
where for <'b> &'b mut T: AddAssign<&'b T>,
Run Code Online (Sandbox Code Playgroud)
...你会写:
where for <'b> T: AddAssign<&'b T>,
Run Code Online (Sandbox Code Playgroud)
(到目前为止,其他线路没有改变)
但是,您注意到代码仍然无法编译:
pub trait AddAssign<Rhs = Self> {
fn add_assign(&mut self, rhs: Rhs);
}
Run Code Online (Sandbox Code Playgroud)
原因很简单:根本没有AddAssignfor 原始类型的实现,它将不可变引用作为 rhs (文档)。我不知道这是否是一个疏忽——可能值得在 Rust 存储库上提出一个问题。
为了验证上述代码是否有效,我编写了自己的类型并AddAssign适当实现:Playground。
| 归档时间: |
|
| 查看次数: |
1553 次 |
| 最近记录: |