使用Option :: map to Box :: new特征对象不起作用

Tom*_*řák 4 rust

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,
    };
}
Run Code Online (Sandbox Code Playgroud)

Rustc 1.23.0.为什么第一种方法不能编译?我错过了一些明显的东西,或者......嗯?

Ste*_*fan 5

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)
}
Run Code Online (Sandbox Code Playgroud)

并使用它.map(box_new_unsized).参见游乐场.

  • 啊哈,我错过了隐式发生在幕后的 `as Box&lt;FooTrait&gt;`,而且(回想起来很明显)事实是 `as` 不是*一个无操作,创建一个特征对象不仅仅是一个游戏具有类型归属,但实际操作。如果我想使用`.map`,我可以明确`let Maybe_trait = Maybe_struct.map(|x| Box::new(x) as Box&lt;FooTrait&gt;);`。我还必须完全消化强制、“Unsize”和朋友们。谢谢。 (3认同)