Hello,
I tried to define a generic implementation of a trait for all type
than implement a trait + IntoIterator is implemented for ref on the type.
After quite a bit of research, I finally found the syntax to express this in where close, by when I tried it's don't work. The compiler say :
error[E0599]: the method
print_values
exists for structRangeWithInc
, but its trait bounds were not satisfied
But if I manually implement the trait for the type, the compiler say :
warning: conflicting implementations of trait
ListValues
for typeRangeWithInc
Someone can tell me if I have made an error in the ListValues
generic implementation definition, or if it's should work and I need to create a bug ?
Thank you
Example code :
trait Range {
fn name(&self) -> &str;
fn start(&self) -> u32;
fn end(&self) -> u32;
}
trait ListValues {
fn print_values(&self) -> String;
}
struct RangeWithInc {
end: u32,
inc: u32,
}
impl RangeWithInc {
pub fn inc(&self) -> u32 {
self.inc
}
}
impl Range for RangeWithInc {
fn name(&self) -> &str {
"demo"
}
fn start(&self) -> u32 {
0
}
fn end(&self) -> u32 {
self.end
}
}
impl<'a> IntoIterator for &'a RangeWithInc {
type Item = u32;
type IntoIter = DataIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
DataIterator {
range: self,
progress: 0,
}
}
}
struct DataIterator<'a> {
range: &'a RangeWithInc,
progress: u32,
}
impl Iterator for DataIterator<'_> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.progress += self.range.inc();
if self.progress < self.range.end() {
Some(self.range.start() + self.progress)
} else {
None
}
}
}
// generic impl of `ListValues`
impl<I, U> ListValues for U
where
I: Iterator<Item = u32>,
for<'a> &'a U: IntoIterator<Item = u32, IntoIter = I>,
U: Range,
{
fn print_values(&self) -> String {
let init = String::from(self.name());
//let ref_self: &U = self.into::<R>();
let iter = self.into_iter();
iter.fold(init, |val, cur| format!("{val}, {cur}"))
}
}
// // dedicated impl of `ListValues`
// impl ListValues for RangeWithInc {
// fn print_values(&self) -> String {
// let init = String::from(self.name());
// //let ref_self: &U = self.into::<R>();
// let iter = self.into_iter();
// iter.fold(init, |val, cur| format!("{val}, {cur}"))
// }
// }
fn main() {
let range = RangeWithInc { end: 25, inc: 3 };
let values = range.print_values();
println!("{values}");
}