如何将迭代器适配器与函数返回 impl Trait 作为 IntoIterator 的 IntoIter 关联类型一起使用?
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
(a.k.a。,展平为 [= 上的迭代器18=]).这可以使用 flatten
和 map
来完成,但我不确定如何为迭代器的 map
部分指定 return 类型。
据我了解,每个函数都有一个独特的类型。有什么方法可以访问此特定类型(a.k.a,函数 return 是一个使用此确切函数的 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())
}
}
或者,我很乐意使用 the type_alias_impl_trait feature 来解决这个问题,但这会导致生命周期错误,我认为这是一个编译器错误。
#![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()
}
}
我在 playground 中拥有此代码的所有三个版本 here
这是 answered on r/rust by u/leo60228。
You have to explicitly specify the nalgebra iterator type. This results in somewhat of a generic soup (like most things in 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()
}
}
我有一个结构 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
(a.k.a。,展平为 [= 上的迭代器18=]).这可以使用 flatten
和 map
来完成,但我不确定如何为迭代器的 map
部分指定 return 类型。
据我了解,每个函数都有一个独特的类型。有什么方法可以访问此特定类型(a.k.a,函数 return 是一个使用此确切函数的 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())
}
}
或者,我很乐意使用 the type_alias_impl_trait feature 来解决这个问题,但这会导致生命周期错误,我认为这是一个编译器错误。
#![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()
}
}
我在 playground 中拥有此代码的所有三个版本 here
这是 answered on r/rust by u/leo60228。
You have to explicitly specify the nalgebra iterator type. This results in somewhat of a generic soup (like most things in 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()
}
}