Хранить лямбда-возвращающий итератор в структуре - PullRequest
0 голосов
/ 23 июня 2019

Я хочу сохранить лямбду, которая будет возвращать итератор в структуре. Лямбда нужна, потому что не все контейнеры реализуют функцию iter() (например, String::chars()), поэтому мне нужен универсальный способ получить итератор из контейнера.

use std::marker::PhantomData;

struct Foo<F, V, T> {
  foo : F,
  ph: PhantomData<V>,
  ph2: PhantomData<T>,
}

impl<F, V, T> Foo<F, V, T> where
  F: Fn(V) -> dyn Iterator<Item = T> {
}

К сожалению, я получаю следующую ошибку:

error[E0277]: the size for values of type `(dyn std::iter::Iterator<Item=T> + 'static)` cannot be known at compilation time
  --> main.rs:9:1
   |
9  | / impl<F, V, T> Foo<F, V, T> where
10 | |   F: Fn(V) -> dyn Iterator<Item = T>
11 | | {
12 | |
13 | | }
   | |_^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::iter::Iterator<Item=T> + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required by `std::ops::FnOnce`

Я надеюсь, что понимаю его значение, но я не знаю, как это исправить.

1 Ответ

1 голос
/ 23 июня 2019

Объект черты, такой как dyn Iterator<Item = T>, не имеет размера, известного во время компиляции. Одним из следствий этого является то, что «необработанный» объект trait не может быть возвращен функцией - компилятору необходимо заранее знать, сколько места нужно зарезервировать в стеке при вызове функции.

Чтобы получить известный размер, оберните объект черты в ссылку или умный указатель. Например, Box:

impl<F, V, T> Foo<F, V, T>
where
    F: Fn(V) -> Box<dyn Iterator<Item = T>>,
{

}
...