Ich habe eine Fibonacci
Struktur, die als Iterator für alles, das One
, Zero
, Add
und Clone
implementiert, verwendet werden kann. Dies funktioniert hervorragend für alle Integer-Typen.Wie schreibe ich eine Merkmalsbindung zum Hinzufügen von zwei Referenzen eines generischen Typs?
Ich möchte diese Struktur für BigInteger
Typen verwenden, die mit einem Vec
implementiert werden und sind teuer zu clone()
auf rufen. Ich möchte Add
auf zwei Referenzen auf T
verwenden, die dann eine neue T
zurückgibt (kein Klonen dann).
Für das Leben von mir, dass ich nicht kann man machen, die zwar ...
Arbeits kompiliert:
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);
}
Wunsch:
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);
}
Dies gibt den Fehler
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;
| ^^^^^^^^^^
Sie könnten interessiert sein an [std :: ops :: AddAssign] (https://doc.rust-lang.org/std/ops/trait.AddAssign.html), deren RFC in der letzten Kommentar-Periode ist: it lässt Sie den "+ =" Operator überladen. Dies würde es ermöglichen, zumindest '.clone()' Aufrufe für die Addition zu vermeiden. –
Das wäre ein Klon weniger :) Ich kann aber beide nicht loswerden. 12+ Wochen bis das, obwohl ich denke .. – dten
Zwei weniger Klone tatsächlich: 'self.next = self.next.clone() + self.curr.clone();' würde durch 'self.next + = & self ersetzt werden. curr; '. –