简体   繁体   English

如何在Rust中编写一个函数,该函数接受Item满足特征的任何迭代器?

[英]How do I write a function in Rust that accepts any iterator whose Item fulfills a trait?

Here is a contrived example of what I'm trying to achieve: 这是我想要达到的目标的人为示例:

trait Double {
    fn get(&self) -> i32;
}

impl Double for i32 {
    fn get(&self) -> i32 { self * 2 }
}

fn foo<'a, I: Iterator<Item = &'a Double>>(is: I) {
    for i in is {
        println!("{}", i.get());
    }
}

fn main() {
    let is = vec![1, 2, 3, 4];
    foo(is.into_iter());
}

The error here says "expected integral variable, found &Double ". 错误在这里显示为“期望的积分变量,找到&Double ”。

I'm having trouble googling for this as everywhere talks about iterators as traits. 我到处都在寻找麻烦,因为到处都在谈论迭代器是特质。 Is what I'm trying to do even possible? 我要做什么甚至有可能吗?

Yes, it's possible. 是的,有可能。 You need to use a where clause to specify a bound on the associated type I::Item . 您需要使用where子句来指定关联类型I::Item的绑定。

fn foo<I>(is: I)
    where I: Iterator,
          I::Item: Double,
{
    for i in is {
        println!("{}", i.get());
    }
}

(I've also moved the I: Iterator bound to the where clause to keep all the bounds together.) (我还将I: Iterator绑定到where子句,以使所有边界保持在一起。)

The bound Iterator<Item = &'a Double>> says that you want an iterator which yields items of exactly the type &Double which denotes the trait object of the trait Double . 绑定的Iterator<Item = &'a Double>>表示您想要一个迭代器,该迭代器产生的类型&Double完全相同,该类型表示特性Double的特性对象。 But you want an iterator that yields any type which implements the trait Double . 但是,您需要一个迭代器,该迭代器可以产生实现特征Double任何类型。 This sounds very similar and thus confusing, but this is all about dynamic vs static dispatch. 这听起来很相似,因此令人困惑,但这全是关于动态与静态分派。 You should read the Rust book chapter about trait objects to understand what exactly is going on. 您应该阅读有关特质对象的Rust书一章,以了解到底发生了什么。

But a quick summary: there is a difference between writing 但快速总结:写作之间有区别

fn foo<T: MyTrait>(t: &T) {}

and

fn foo(t: &MyTrait) {}

You wrote code equivalent to the latter, but actually want the former. 您编写了与后者等效的代码,但实际上要使用前者。


So how do you express your intend in code? 那么,您如何用代码表达您的意图? One possibility is to introduce another type parameter! 一种可能是引入另一种类型参数!

fn foo<'a, T, I>(is: I) 
    where T: Double,
          I: Iterator<Item = &'a T>,
{
    for i in is {
        println!("{}", i.get());
    }
}

But you can also just bound the associated type of the iterator (see Francis Gagné's answer ): 但是您也可以绑定迭代器的关联类型(请参见FrancisGagné的答案 ):

fn foo<I>(is: I) 
    where I: Iterator,
          I::Item: Double,
{ ... }

However, these two versions are slightly different as one accepts an iterator over references to types implementing Double while the other one iterates over types implementing Double directly. 但是,这两个版本略有不同,因为一个版本接受对实现Double类型的引用的迭代器,而另一个版本对直接实现Double类型的迭代进行迭代。 Just use what fits you the best or generalize those two things with traits like AsRef . 只需使用最适合您的方法或使用AsRef特征概括这两件事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何编写接受特征或指向特征的智能指针(Box、Rc 等)的通用代码? - How do I write generic code that accepts either a trait or a smart pointer to the trait (Box, Rc, etc)? 如何从特征函数返回任意类型的迭代器? - How do I return an iterator of arbitrary type from a trait function? 如何编写接受任何数字类型的通用 function? - How to write a generic function that accepts any numerical type? 如何构造可能实现特征的许多潜在结构中的任何一个? - How do I construct any of potentially many structs that implement a trait? 在 Rust 中,将泛型与整数进行比较需要什么特征 - In Rust, what trait do I need to compare a generic to an integer 在Rust中使用接受闭包的方法创建对象安全的特性 - Create an Object-safe Trait in Rust with a method that accepts a closure 如何在 Rust 中没有特征对象的特征的多个实现者之间进行选择? - How can I choose between multiple implementors of a trait without trait objects in Rust? rust:定义一个通用函数,该函数将接受对实现特定特征的任何可迭代事物的借用 - rust: Define a generic function that will accept a borrow to any iterable of things that implement a certain trait Rust:为比较长度的泛型函数定义特征 - Rust: defining trait for generic function that compares length 如何编写带有`u32`或`&amp;u32`的任何迭代器的通用函数? - How to write a generic function taking any iterator of `u32` or `&u32`?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM