I have the following code:
struct Container<T>(T);
struct MyStruct<T> {
entries: Vec<T>,
}
impl<'a, T> IntoIterator for &'a MyStruct<Container<T>> {
type Item = &'a Container<T>;
type IntoIter = std::slice::Iter<'a, Container<T>>;
fn into_iter(self) -> Self::IntoIter {
let entries = &self.entries;
entries.into_iter()
}
}
fn main() {
let my_struct: MyStruct<Container<usize>> = MyStruct {
entries: vec![
Container(0),
Container(1),
Container(2),
Container(3),
Container(4),
],
};
for c in my_struct.into_iter() {
println!("{}", c.0);
// I want c to be usize not Container<usize>.
println!("{}", c);
}
}
I would like the iterator obtained from into_iter()
to produce the inner value of Container
.
I tried like this:
impl<'a, T> IntoIterator for &'a MyStruct<Container<T>> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
let entries = &self.entries;
// Map to the inner value.
entries.into_iter().map(|c| c.0)
}
}
But it doesn't compile with the error below:
error[E0308]: mismatched types
--> src/main.rs:25:9
|
21 | fn into_iter(self) -> Self::IntoIter {
| -------------- expected `std::slice::Iter<'_, T>` because of return type
...
25 | entries.into_iter().map(|c| c.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::slice::Iter`, found struct `Map`
|
= note: expected struct `std::slice::Iter<'_, T>`
found struct `Map<std::slice::Iter<'_, Container<T>>, [closure@src/main.rs:25:33: 25:40]>`
If I follow the suggestions I get more and more complicated errors.
CodePudding user response:
This works:
struct Container<T>(T);
struct MyStruct<T> {
entries: Vec<T>,
}
impl<T> IntoIterator for MyStruct<Container<T>> {
type Item = T;
type IntoIter = std::iter::Map<std::vec::IntoIter<Container<T>>, fn(Container<T>) -> T>;
fn into_iter(self) -> Self::IntoIter {
self.entries.into_iter().map(|c| c.0)
}
}
fn main() {
let my_struct: MyStruct<Container<usize>> = MyStruct {
entries: vec![Container(0), Container(1), Container(2), Container(3)],
};
for c in my_struct.into_iter() {
println!("{}", c);
}
}
CodePudding user response:
You could implement Deref instead, and then you would only need to add some stars (*) to deref enough:
use std::ops::Deref;
struct Container<T>(T);
impl<T> Deref for Container<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
struct MyStruct<T> {
entries: Vec<T>,
}
impl<T> Deref for MyStruct<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.entries
}
}
fn main() {
let my_struct: MyStruct<Container<usize>> = MyStruct {
entries: vec![Container(0), Container(1), Container(2), Container(3)],
};
for c in my_struct.iter() {
println!("{}", c.0);
println!("{}", **c);
}
}