dte*_*ten 9 generics fibonacci rust
我有一个Fibonacci可以用作任何一个迭代器实现结构One,Zero,Add和Clone.这适用于所有整数类型.
我想将这个结构用于BigInteger使用a实现Vec并且调用昂贵的类型clone().我想Add在两个引用上T使用然后返回一个新的T(然后没有克隆).
对于我的生活,我不能制作一个虽然编译的...
工作:
extern crate num;
use std::ops::Add;
use std::mem;
use num::traits::{One, Zero};
pub struct Fibonacci<T> {
curr: T,
next: T,
}
pub fn new<T: One + Zero>() -> Fibonacci<T> {
Fibonacci {
curr: T::zero(),
next: T::one(),
}
}
impl<'a, T: Clone + Add<T, Output = T>> Iterator for Fibonacci<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
mem::swap(&mut self.next, &mut self.curr);
self.next = self.next.clone() + self.curr.clone();
Some(self.curr.clone())
}
}
#[test]
fn test_fibonacci() {
let first_12 = new::<i64>().take(12).collect::<Vec<_>>();
assert_eq!(vec![1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144], first_12);
}
Run Code Online (Sandbox Code Playgroud)
期望:
extern crate num;
use std::ops::Add;
use std::mem;
use num::traits::{One, Zero};
pub struct Fibonacci<T> {
curr: T,
next: T,
}
pub fn new<T: One + Zero>() -> Fibonacci<T> {
Fibonacci {
curr: T::zero(),
next: T::one(),
}
}
impl<'a, T: Clone + 'a> Iterator for Fibonacci<T>
where
&'a T: Add<&'a T, Output = T>,
{
type Item = T;
fn next(&mut self) -> Option<T> {
mem::swap(&mut self.next, &mut self.curr);
self.next = &self.next + &self.curr;
Some(self.curr.clone())
}
}
#[test]
fn test_fibonacci() {
let first_12 = new::<i64>().take(12).collect::<Vec<_>>();
assert_eq!(vec![1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144], first_12);
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:27:21
|
27 | self.next = &self.next + &self.curr;
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 25:5...
--> src/main.rs:25:5
|
25 | / fn next(&mut self) -> Option<T> {
26 | | mem::swap(&mut self.next, &mut self.curr);
27 | | self.next = &self.next + &self.curr;
28 | | Some(self.curr.clone())
29 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:27:21
|
27 | self.next = &self.next + &self.curr;
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
--> src/main.rs:19:1
|
19 | / impl<'a, T: Clone + 'a> Iterator for Fibonacci<T>
20 | | where
21 | | &'a T: Add<&'a T, Output = T>,
22 | | {
... |
29 | | }
30 | | }
| |_^
note: ...so that types are compatible (expected std::ops::Add, found std::ops::Add<&'a T>)
--> src/main.rs:27:32
|
27 | self.next = &self.next + &self.curr;
| ^
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:27:34
|
27 | self.next = &self.next + &self.curr;
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 25:5...
--> src/main.rs:25:5
|
25 | / fn next(&mut self) -> Option<T> {
26 | | mem::swap(&mut self.next, &mut self.curr);
27 | | self.next = &self.next + &self.curr;
28 | | Some(self.curr.clone())
29 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:27:34
|
27 | self.next = &self.next + &self.curr;
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
--> src/main.rs:19:1
|
19 | / impl<'a, T: Clone + 'a> Iterator for Fibonacci<T>
20 | | where
21 | | &'a T: Add<&'a T, Output = T>,
22 | | {
... |
29 | | }
30 | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:27:34
|
27 | self.next = &self.next + &self.curr;
| ^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
如何写一个特征绑定添加两个泛型类型的引用?
让我们从一个简化的例子开始:
fn add_things<T>(a: &T, b: &T) {
a + b;
}
Run Code Online (Sandbox Code Playgroud)
这有错误
error[E0369]: binary operation `+` cannot be applied to type `&T`
--> src/lib.rs:2:5
|
2 | a + b;
| ^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `&T`
Run Code Online (Sandbox Code Playgroud)
正如编译器提示的那样,我们需要保证Add实现&T.我们可以通过向我们的类型添加显式生命周期并在我们的特征边界中使用它来直接表达:
use std::ops::Add;
fn add_things<'a, T>(a: &'a T, b: &'a T)
where
&'a T: Add,
{
a + b;
}
Run Code Online (Sandbox Code Playgroud)
接下来,让我们尝试一种稍微不同的方法 - 我们将在函数内部创建一个,而不是提交引用.
fn add_things<T>(a: T, b: T) {
let a_ref = &a;
let b_ref = &b;
a_ref + b_ref;
}
Run Code Online (Sandbox Code Playgroud)
我们得到了同样的错误:
error[E0369]: binary operation `+` cannot be applied to type `&T`
--> src/lib.rs:5:5
|
5 | a_ref + b_ref;
| ^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `&T`
Run Code Online (Sandbox Code Playgroud)
但是,尝试添加与以前相同的修复程序不起作用.这也有点尴尬,因为生命周期与传入的任何参数无关:
use std::ops::Add;
fn add_things<'a, T: 'a>(a: T, b: T)
where
&'a T: Add,
{
let a_ref = &a;
let b_ref = &b;
a_ref + b_ref;
}
Run Code Online (Sandbox Code Playgroud)
error[E0597]: `a` does not live long enough
--> src/lib.rs:7:17
|
3 | fn add_things<'a, T: 'a>(a: T, b: T)
| -- lifetime `'a` defined here
...
7 | let a_ref = &a;
| ^^
| |
| borrowed value does not live long enough
| assignment requires that `a` is borrowed for `'a`
...
11 | }
| - `a` dropped here while still borrowed
Run Code Online (Sandbox Code Playgroud)
将'a生命周期放在impl意味着方法的调用者确定生命周期应该是什么的意义上.由于引用是在方法内部进行的,因此调用者甚至无法看到生命周期是什么.
相反,您希望限制任意生命周期的引用实现特征.这被称为更高级别的特质界限(HRTB):
use std::ops::Add;
fn add_things<T>(a: T, b: T)
where
for<'a> &'a T: Add,
{
let a_ref = &a;
let b_ref = &b;
a_ref + b_ref;
}
Run Code Online (Sandbox Code Playgroud)
应用回原始代码,您非常接近:
impl<T> Iterator for Fibonacci<T>
where
T: Clone,
for<'a> &'a T: Add<Output = T>,
{
type Item = T;
fn next(&mut self) -> Option<T> {
mem::swap(&mut self.next, &mut self.curr);
self.next = &self.next + &self.curr;
Some(self.curr.clone())
}
}
Run Code Online (Sandbox Code Playgroud)
也可以看看: