libstd di Rust ha un'esecuzione del presente, il tratto IntoIterator
.
/// Conversion into an `Iterator`
pub trait IntoIterator {
/// The type of the elements being iterated
type Item;
/// A container for iterating over elements of type `Item`
type IntoIter: Iterator<Item=Self::Item>;
/// Consumes `Self` and returns an iterator over it
fn into_iter(self) -> Self::IntoIter;
}
La caratteristica peculiare ha questa formulazione per valore (self
) esattamente poter esprimere sia “in iteratore” e “prendere in prestito iteratore” semantica.
Dimostrato dalle implementazioni di HashMap IntoIterator
. (Usano le strutture iteratore di hashmap Iter
e IntoIter
.) Ciò che è interessante qui è che il tratto è implementato per il tipo &HashMap<K, V, S>
per esprimere il "prestito iteratore".
impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
impl<K, V, S> IntoIterator for HashMap<K, V, S>
where K: Eq + Hash, S: HashState
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
/// Creates a consuming iterator, that is, one that moves each key-value
/// pair out of the map in arbitrary order. The map cannot be used after
/// calling this.
fn into_iter(self) -> IntoIter<K, V> {
/* ... */
}
}
Se si utilizza un tipo associato, come suggerito nelle risposte qui sotto non è adatto (non può essere), allora si può tornare un 'Box>' invece. Ma questo richiederà un'allocazione dell'heap! –
BurntSushi5