可以通过采用可变引用来移动值吗?

时间:2016-06-02 15:25:03

标签: rust

Playpen

pub trait Skip<I: Iterator> {
    fn skip(&mut self, steps: usize);
}

impl<I: Iterator> Skip<I> for I {
    fn skip(&mut self, mut steps: usize) {
        for _ in self {
            steps -= 1;
            if steps <= 0 {
                break;
            }
        }
    }
}

fn main() {
    let s  = "abc123def";
    let mut chars = s.chars();
    chars.skip(2);
    println!("{:?}", chars.collect::<String>());
}

错误:

error: use of moved value: `chars` [--explain E0382]
  --> <anon>:20:22
19 |>     chars.skip(2);
   |>     ----- value moved here
20 |>     println!("{:?}", chars.collect::<String>());
   |>                      ^^^^^ value used here after move
<anon>:20:22: 20:27: note: in this expansion of format_args!
<anon>:20:22: 20:27: note: in this expansion of print! (defined in <std macros>)
<anon>:20:22: 20:27: note: in this expansion of println! (defined in <std macros>)
note: move occurs because `chars` has type `std::str::Chars<'_>`, which does not implement the `Copy` trait

error: aborting due to previous error
playpen: application terminated with error code 101

1 个答案:

答案 0 :(得分:4)

  

可以通过采用可变参考来移动值吗?

没有。引用不会移动引用的项目。这是一个很大的参考点。

但是,Iterator::skip确实取得了迭代器的所有权,这是一个移动:

fn skip(self, n: usize) -> Skip<Self>

要解决错误,您可以......采取可变参考!

chars.by_ref().skip(2);

但是,请注意,调用迭代器适配器而不使用它不执行任何操作

  

警告:必须使用的未使用结果:迭代器适配器是惰性的,除非消耗

否则不执行任何操作

这里的真正的问题是你没有调用你认为自己的skip。如果您将方法重命名为skip2,则会看到它按预期工作。

这是因为方法查找更喜欢在by-mutable-reference(self)之前接受by-reference(&self)之前的接收器by-value(&mut self)的方法。 / p>

选择与标准库相同的方法名称可能是一个坏主意,特别是对于迭代器,但是非常令人惊讶的是没有打印警告说有多种适用的方法在范围内。

您可以使用Universal Function Call Syntax (UFCS)来指定要调用的实现:

pub trait Skip: Iterator {
    fn skip(&mut self, steps: usize) {
        for _ in self.take(steps) {}
    }
}

impl<I> Skip for I where I: Iterator {}

fn main() {
    let s  = "abc123def";
    let mut chars = s.chars();
    Skip::skip(&mut chars, 2);
    println!("{:?}", chars.collect::<String>());
}