Как использовать адаптер итератора с функцией, возвращающей impl Trait в качестве типа IntoIterator, связанного с IntoIter? - PullRequest
0 голосов
/ 10 марта 2020

У меня есть структура с 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 (иначе, flatten в итератор более f32). Это можно сделать с помощью flatten и map, но я не уверен, как указать тип возвращаемого значения для части map итератора.

Насколько я понимаю, каждая функция имеет уникальный тип , Есть ли способ получить доступ к этому указанному c типу (иначе, функция возвращает итератор 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

1 Ответ

0 голосов
/ 10 марта 2020

Это был ответ на r / rust от u / leo60228 .

Вы должны явно указать тип итератора nalgebra. Это приводит к некоторому универсальному супу c (как и большинство вещей в налгебре): 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()
    }
}
...