Maximilian
Maximilian

Reputation: 8530

Iterate over a reference to Chars

I have a function that receives a reference to Chars:

use std::str::Chars;

fn main() {
    let s = "aoeuaoeu".to_string();
    my_func(&s.chars())
}

fn my_func(chars: &Chars) {
    for x in chars {
        dbg!(x);
    }
}

This doesn't compile, because chars on line 9 is the reference rather than the iterator:

error[E0277]: `&std::str::Chars<'_>` is not an iterator
 --> src/main.rs:9:14
  |
9 |     for x in chars {
  |              ^^^^^ `&std::str::Chars<'_>` is not an iterator
  |
  = help: the trait `std::iter::Iterator` is not implemented for `&std::str::Chars<'_>`
  = note: required by `std::iter::IntoIterator::into_iter`

I've tried whack-a-mole with & and * etc, to no avail. Is there any way of iterating over it without an additional allocation?

I'm not in control of the calling function, so the function does need to take a reference (i.e. can't change the caller to my_func(s.chars().

Upvotes: 1

Views: 731

Answers (1)

Stargateur
Stargateur

Reputation: 26767

The problem is that you hold a immutable reference to Chars you are not free to mutate it and Iterator is only auto implemented for mutable reference impl<I: Iterator + ?Sized> Iterator for &mut I. For the very good reason then next() require &mut self.

You have many solutions: take it as mutable reference, clone it or take it by value:

use std::str::Chars;

fn main() {
    let s = "aoeuaoeu".to_string();
    my_func(&mut s.chars())
}

fn my_func(chars: &mut Chars) {
    for x in chars {
        dbg!(x);
    }
}
use std::str::Chars;

fn main() {
    let s = "aoeuaoeu".to_string();
    my_func(&s.chars())
}

fn my_func(chars: &Chars) {
    for x in chars.clone() {
        dbg!(x);
    }
}
use std::str::Chars;

fn main() {
    let s = "aoeuaoeu".to_string();
    my_func(s.chars())
}

fn my_func(chars: Chars) {
    for x in chars {
        dbg!(x);
    }
}

Take by value is probably what the want.

Upvotes: 3

Related Questions