Использовать Option::map to Box::new объект черты не работает

trait FooTrait {}

struct FooStruct;

impl FooTrait for FooStruct {}

fn main() {
    let maybe_struct: Option<FooStruct> = None;

//  Does not compile, "expected trait FooTrait, found struct `FooStruct`"
//  let maybe_trait: Option<Box<FooTrait>> = maybe_struct.map(Box::new);

    // Compiles fine
    let maybe_trait: Option<Box<FooTrait>> = match maybe_struct {
        Some(s) => Some(Box::new(s)),
        None => None,
    };
}

Rustc 1.23.0. Почему первый подход не компилируется? Я что-то упускаю из виду или... да?

1 ответ

Решение

Box::new работает только с размерами; то есть, он принимает значение размера типа T и возвращается Box<T>, В определенных местах Box<T> может быть приведен в Box<U> (если T: Unsize<U>).

Такого принуждения не бывает в .map(Box::new), но делает в Some(Box::new(s)); последний в основном такой же, как Some(Box::new(s) as Box<FooTrait>),

Вы можете создать (в ночное время) свой собственный конструктор ящиков, который возвращает ящики нестандартных типов, например:

#![feature(unsize)]

fn box_new_unsized<T, U>(v: T) -> Box<U>
where
    T: ::std::marker::Unsize<U>,
    U: ?Sized,
{
    Box::<T>::new(v)
}

и использовать его как .map(box_new_unsized), Смотрите Детская площадка.

Другие вопросы по тегам