【问题标题】:Why can I create boxed iterator from Vec and not from array? [duplicate]为什么我可以从 Vec 而不是数组创建盒装迭代器? [复制]
【发布时间】:2020-06-18 14:46:40
【问题描述】:

下面的代码可以编译,但如果传递给函数“f”的“args”从 Vec 更改为字符串数组,则不会。我试图理解为什么。我认为这与所有权规则有关,但我可以澄清一下。谢谢。

fn f(args: Box<dyn Iterator<Item=String>>) {
    for arg in args {
        println!("{}", arg)
    }
}


fn main() {
    let args = vec!["one_arg".to_string()]; // If changed to array, I get error below
    f(Box::new(args.into_iter()));
}

如果 vec!["one_arg".to_string()];改成:["one_arg".to_string()];,结果就是下面的错误。

error[E0271]: type mismatch resolving `<std::slice::Iter<'_, std::string::String> as std::iter::Iterator>::Item == std::string::String`
  --> src/main.rs:10:7
   |
10 |     f(Box::new(args.into_iter()));
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found reference
   |
   = note: expected struct `std::string::String`
           found reference `&std::string::String`
   = note: required for the cast to the object type `dyn std::iter::Iterator<Item = std::string::String>`

【问题讨论】:

    标签: arrays rust ownership vec


    【解决方案1】:

    原因是因为Vec::into_iter 在其项目上返回一个迭代器,而slice::into_iter 在对其项目的引用上返回一个迭代器。因此,args.into_iter() 是 Iterator&lt;Item=&amp;String&gt; 而不是 Iterator&lt;Item=String&gt; 当 args 是一个切片时。附带说明一下,不要 Box 和 dyn Iterator 而是使用泛型:

    fn f<I: Iterator<Item=String>>(args: I) {
        for arg in args {
            println!("{}", arg)
        }
    }
    
    
    fn main() {
        let args = vec!["one_arg".to_string()];
        f(args.into_iter());
    }
    

    【讨论】:

    • 好的。但是我的问题就变成了(因为我不清楚;-)),为什么?如果我不得不接受它,我会接受它,但为什么会有不同的行为呢?这是否意味着数组中的对象永远无法移动?并感谢您使用泛型 BTW 的建议。
    • @BillBarrington 这主要是一个历史事故,目前不容易修复:github.com/rust-lang/rust/pull/65819
    • 是的,您不能将值移出 rust 的数组/切片。如果你想模拟移动,你可以使用mem::take之类的东西,它将一个值替换为默认值并返回所取的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 2020-01-22
    • 2021-10-27
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多