繁体   English   中英

Rust 迭代器泛型问题,无法编译

[英]Rust iterator generics question, can't compile

我正在尝试将泛型用于特征中的迭代器,并且很难理解为什么它不能编译。

struct B {
    values: Vec<(i64, i64)>,
}

pub trait IterableCustom {
    fn get_iterator<'a, I>(&self) -> I
    where
        I: Iterator<Item = &'a (i64, i64)>;
}

impl IterableCustom for B {
    fn get_iterator<'a, I>(&self) -> I
    where
        I: Iterator<Item = &'a (i64, i64)>,
    {
        let rev = self.values.iter().rev();
        rev
    }
}

它抛出一个错误:

error[E0308]: mismatched types
  --> src/lib.rs:17:9
   |
12 |     fn get_iterator<'a, I>(&self) -> I
   |                         -            - expected `I` because of return type
   |                         |
   |                         this type parameter
...
17 |         rev
   |         ^^^ expected type parameter `I`, found struct `Rev`
   |
   = note: expected type parameter `I`
                      found struct `Rev<std::slice::Iter<'_, (i64, i64)>>`

For more information about this error, try `rustc --explain E0308`.

操场

关于I我们唯一知道的是I实现了Iterator<Item = &'a (i64, i64)> ,所以I可以是任何满足 trait bound 的迭代器类型。 因此, rev的类型并不总是等于I

如果没有 GAT 或存在类型(它们还不是稳定的 Rust),目前重写它的最好方法是返回一个装箱的 trait 对象。

struct B {
    values: Vec<(i64, i64)>,
}

pub trait IterableCustom {
    fn get_iterator(&self) -> Box<dyn Iterator<Item = &(i64, i64)> + '_>;
}

impl IterableCustom for B {
    fn get_iterator(&self) -> Box<dyn Iterator<Item = &(i64, i64)> + '_> {
        let rev = self.values.iter().rev();
        Box::new(rev)
    }
}

夜间解决方案

使用泛型关联类型,代码可以这样重写。

#![feature(generic_associated_types)]

struct B {
    values: Vec<(i64, i64)>,
}

pub trait IterableCustom {
    type Iter<'a>: Iterator<Item = &'a (i64, i64)>
    where
        Self: 'a;
    fn get_iterator<'a>(&'a self) -> Self::Iter<'a>;
}

impl IterableCustom for B {
    type Iter<'a> = std::iter::Rev<std::slice::Iter<'a, (i64, i64)>>;
    fn get_iterator<'a>(&'a self) -> Self::Iter<'a> {
        self.values.iter().rev()
    }
}

使用存在类型,可以进一步减少过于冗长的std::iter::Rev<...>类型。

type Iter<'a> = impl Iterator<Item = &'a (i64, i64)>
where
    Self: 'a;

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM