Как реализовать черту, когда один из связанных типов невозможно назвать? - PullRequest
10 голосов
/ 16 апреля 2019

У меня есть функция, которая возвращает impl Trait, поэтому у меня нет доступа к конкретному типу возврата.Мне нужно использовать возвращаемое значение этой функции в качестве связанного типа в признаке.Как мне это сделать?

Вот упрощенный пример:

fn f() -> impl Iterator<Item = u8> {
    std::iter::empty()
}

struct S;

impl IntoIterator for S {
    type Item = u8;
    type IntoIter = (); // What can I write here ?

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}

Можно ли вообще это сделать (не прибегая к боксу итератора)?

1 Ответ

8 голосов
/ 16 апреля 2019

К сожалению, вы не можете.По крайней мере, пока.

Существует RFC, Именованные экзистенты и объявления переменных Impl Trait ( отслеживание проблемы ), которые позволят вам объявить открытый тип имя на уровне модуля, тип которого определение выводится из того, как оно используется в модуле.Пользователи модуля могут ссылаться на этот тип по его общедоступному имени, и его можно использовать как связанный тип.

Трудно догадаться, когда стабилизируется новая функция, а между тем на самом деле не так много хорошихопции.Помимо вещей, которые могут работать только из-за особенностей вашего варианта использования, общий обходной путь заключается в использовании объекта черты:

impl IntoIterator for S {
    type Item = u8;
    type IntoIter = Box<dyn Iterator<Item = u8>>;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(f())
    }
}

Если допустимо использование ночных функций, вы можете помочь проверитьRFC до стабилизации:

#![feature(existential_type)]

impl IntoIterator for S {
    type Item = u8;
    existential type IntoIter: Iterator<Item = u8>;

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}
...