I have a trait
trait Foo<T> : Iterator<Item=T> {
fn bar(&mut self) -> f64;
}
I want to implement this trait once for a type T
(in my case f64
) over all its reference types (f64
, &'a f64
, and &'a mut f64
) since logically it doesn't matter.
I currently have
impl<T: Iterator<Item = f64>> Foo<f64> for T {
fn bar(&mut self) -> f64 {
// duplicated code
}
}
impl<'a, T: Iterator<Item = &'a f64>> Foo<&'a f64> for T {
fn bar(&mut self) -> f64 {
// duplicated code
}
}
impl<'a, T: Iterator<Item = &'a mut f64>> Foo<&'a mut f64> for T {
fn bar(&mut self) -> f64 {
// duplicated code
}
}
Is there a good way to accomplish this without duplication?
You can use the Borrow
trait for this. If you look at the implementors in the documentation page, the first three are relevant here: it means that f64
, &'a f64
and &'a mut f64
all implement Borrow<f64>
. You'll have to call the borrow
method on each value produced by the iterator to obtain a &f64
.
use std::borrow::Borrow;
impl<T> Foo<T::Item> for T
where T: Iterator,
T::Item: Borrow<f64>
{
fn bar(&mut self) -> f64 {
unimplemented!()
}
}
By the way, it doesn't really make sense to define a type parameter on the trait and at the same time put a constraint between that type parameter and a supertrait's associated type. A type T
can only have one implementation of Iterator
, therefore it can only have one implementation of Foo
as well, despite the type parameter suggesting that it could implement many different Foo<T>
traits. Therefore, the type parameter on Foo
is completely redundant (you can just use the supertrait's associated types instead of the type parameter). Thus the code should look more like this:
use std::borrow::Borrow;
trait Foo: Iterator {
fn bar(&mut self) -> f64;
}
impl<T> Foo for T
where T: Iterator,
T::Item: Borrow<f64>
{
fn bar(&mut self) -> f64 {
unimplemented!()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With