如何从特质函数返回任意类型的迭代器?

3

我有以下代码(参见链接),我想实现一个trait来返回一个迭代器:

trait MyTrait<V> {
    type Iter: Iterator<Item = V>;
    fn produce_iter(&self) -> Self::Iter;
}

struct MyStruct<V> {
    values: Vec<V>,
}

impl<V> MyTrait<V> for MyStruct<V>
where
    V: Clone,
{
    type Iter = std::vec::IntoIter<V>;

    fn produce_iter(&self) -> Self::Iter {
        self.values.clone().into_iter()
    }
}

fn main() {
    let s = MyStruct {
        values: vec![1, 2, 3],
    };

    s.produce_iter().for_each(|v| println!("{:?}", v));
}

然而,如果我想让我的fn produce_iter(&self)实现更加复杂,例如

fn produce_iter(&mut self) -> Self::Iter {
    self.values
        .clone()
        .into_iter()
        .flat_map(|v| vec![v, v].into_iter())
        .into_iter()
}

替代

fn produce_iter(&mut self) -> Self::Iter {
    self.values.clone().into_iter()
}

我遇到了 error[E0308]: mismatched types 问题,试图弄清楚 type Iter = std::vec::IntoIter<V>; 应该改成什么。
有没有一种“泛型化”错误的方法,使得 fn produce_iter(&self) 可以产生任意复杂的迭代器,而不必担心我为 type Iter 设置了什么?也许我应该从不同的角度看待这个问题?

1
如果没有关联类型,你可以使用impl返回来隐藏复杂性。但是由于存在关联类型,在这种情况下我不知道有什么解决方法。 - Silvio Mayolo
细节问题:当值为Vec时,您可以使用数组代替vec!,并优先使用iter().cloned()而不是.clone().into_iter() - Chayim Friedman
2个回答

0

在稳定版 Rust 中,无法通过通用方式返回值,返回值始终是具体类型或根据输入类型确定的。返回类型必须完全拼写出来。

但是,可以通过 trait 对象返回多个类型。Rust 书中了解更多有关 trait 对象的信息。

不要从 produce_iter 返回具体类型,而是返回一个 Box<dyn Iterator<Item = V>> trait 对象。

trait MyTrait<V> {
    fn produce_iter(&self) -> Box<dyn Iterator<Item = V>>;
}

struct MyStruct<V> {
    values: Vec<V>,
}

impl<V> MyTrait<V> for MyStruct<V>
where
    V: Clone + 'static,
{
    fn produce_iter(&self) -> Box<dyn Iterator<Item = V>> {
    Box::new(
        self.values
            .clone()
            .into_iter()
            .flat_map(|v| vec![v.clone(), v].into_iter())
        )
    }
}

fn main() {
    let s = MyStruct {
        values: vec![1, 2, 3],
    };

    s.produce_iter().for_each(|v| println!("{:?}", v));
}

但要注意,特质对象比具体类型慢,因为特质对象在运行时使用动态分派。


0
在 Nightly 版本中,您可以使用 type_alias_impl_trait
#![feature(type_alias_impl_trait)]

impl<V> MyTrait<V> for MyStruct<V>
where
    V: Clone + std::ops::Mul,
{
    type Iter = impl Iterator<Item = V>;

    fn produce_iter(&self) -> Self::Iter {
        self.values
            .clone()
            .into_iter()
            .flat_map(|v| vec![v, v].into_iter())
            .into_iter()
    }
}

在稳定版本中,您必须使用Box<dyn Iterator>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接