I am trying to write a function that takes any iterable to a generic type as input and loops over the elements. Here is a working example
pub fn test1<'a, IterableT, ItemT>(nodes: &'a IterableT)
where
&'a IterableT: IntoIterator<Item = &'a ItemT>,
ItemT: 'a + Debug
{
for x in nodes {
println!("consuming or iterating: {:?}!", x);
}
}
This works with reference types. I struggle to implement a version that works with both regular types and references. The closest I have got it the following
pub fn test1<IterableT>(nodes: IterableT)
where
IterableT: IntoIterator,
IterableT::Item: Debug
{
for x in nodes {
println!("consuming or iterating: {:?}!", x);
}
}
This works as long as the reference version of the type I am using implements IntoIterator (for example vec, &vec and &mut vec). The problem is that I can't reintroduce the ItemT generic since then the underlying Item is narrowed down to one of Item or &Item
pub fn test1<IterableT, ItemT>(nodes: IterableT)
where
IterableT: IntoIterator<Item = ItemT>, // alternatively IntoIterator<Item = &ItemT>
ItemT: Debug
{
for x in nodes {
println!("consuming or iterating: {:?}!", x);
}
}
Depending on whether I use IntoIterator<Item = ItemT> or IntoIterator<Item = &ItemT>, this works with vec or &vec but not both. A hacky workaround is to specify IterableT::Item: Into<ItemT>, but this only works if the underlying type implements the Into traits (so this will work with built-in types like i32, i64, but not for some custom made struct).
Is there a way to indicate that Item can either be ItemT or &ItemT in the where clause? The reason I need to introduce ItemT is because it is a generic variable of the parent struct that this function is a part of. I need to accept iterators specifically with that type.
You can use
std::borrow::Borrowto treatTand&Tthe same.In action:
Output:
Note that because the
Borrowtrait has a type parameter, you have to provide the correct type forTexplicitly at the call site; Rust will not be able to infer the type you want.