Использовать 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)
, Смотрите Детская площадка.