繁体   English   中英

如何将迭代器适配器与返回 impl Trait 作为 IntoIter 关联类型的 IntoIterator 的函数一起使用?

[英]How do I use a iterator adapter with a function returning impl Trait as the IntoIter associated type of IntoIterator?

我有一个带有Vec<nalgebra::Vector3<f32>>

use nalgebra::Vector3;

struct VecOfVector {
    data: Vec<Vector3<f32>>,
}

fn float_iter_vector(vec: &mut Vector3<f32>) -> impl Iterator<Item = &mut f32> {
    vec.iter_mut()
}

我需要实现IntoIterator以获取对该结构的可变引用,其中Item类型为&mut f32 (也就是在f32展平为迭代器)。 这可以使用flattenmap来完成,但我不确定如何为迭代器的map部分指定返回类型。

根据我的理解,每个函数都有一个独特的类型。 有没有办法访问这个特定类型(也就是,该函数使用这个确切的函数返回一个Map迭代器)?

use std::iter::{Flatten, Map};
use std::slice::IterMut;

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    // how do I specify type of "float_iter_vector"?
    type IntoIter = Flatten<Map<IterMut<'a, f32>, float_iter_vector>>;

    fn into_iter(self) -> Self::IntoIter {
        self.data.iter_mut().map(float_iter_vector).flatten()
    }
}

我可以用装箱解决这个问题,但我担心这会导致迭代器不被内联,它被用在性能敏感的代码中。 LLVM 仍然能够内联它吗?

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    type IntoIter = Box<dyn Iterator<Item = Self::Item> + 'a>;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(self.data.iter_mut().map(float_iter_vector).flatten())
    }
}

或者,我很乐意使用type_alias_impl_trait 功能解决这个问题,但这会导致我认为是编译器错误的终生错误。

#![feature(type_alias_impl_trait)]

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    // hidden type error (likely compiler bug?)
    type IntoIter = impl Iterator<Item = &'a mut f32> + 'a;

    fn into_iter(self) -> Self::IntoIter {
        self.data.iter_mut().map(float_iter_vector).flatten()
    }
}

我在这里的操场上拥有此代码的所有三个版本

我也在r/rust 上发布了这个问题

u/leo60228 在 r/rust 上回答了这个问题

您必须明确指定 nalgebra 迭代器类型。 这会产生某种通用的汤(就像 nalgebra 中的大多数东西一样): https ://play.rust-lang.org/ ? version = nightly & mode = debug & edition = 2018 & gist = 715819c2b93592bae96f819bb020264f

use nalgebra::base::iter::MatrixIterMut;
use nalgebra::dimension::*;
use nalgebra::storage::Owned;
use nalgebra::Vector3;

struct VecOfVector {
    data: Vec<Vector3<f32>>,
}

fn float_iter_vector(vec: &mut Vector3<f32>) -> MatrixIterMut<f32, U3, U1, Owned<f32, U3, U1>> {
    vec.iter_mut()
}

type FloatIterVector =
    for<'a> fn(&'a mut Vector3<f32>) -> MatrixIterMut<'a, f32, U3, U1, Owned<f32, U3, U1>>;

use std::iter::{Flatten, Map};
use std::slice::IterMut;

impl<'a> IntoIterator for &'a mut VecOfVector {
    type Item = &'a mut f32;

    type IntoIter = Flatten<Map<IterMut<'a, Vector3<f32>>, FloatIterVector>>;

    fn into_iter(self) -> Self::IntoIter {
        self.data
            .iter_mut()
            .map(float_iter_vector as FloatIterVector)
            .flatten()
    }
}

暂无
暂无

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

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