有什么方法可以将Box <box <foo + =“” send =“” >>转换为Box <box <foo >>?

时间:2018-07-20 17:28:59

标签: rust

考虑这样的代码:

trait Foo {
    fn foo(&self);
}

fn consume_func(b: Box<Box<Foo>>) {
    unimplemented!();
}

fn produce_func() -> Box<Box<Foo + Send>> {
    unimplemented!();
}

fn main() {
    let b = produce_func();
    consume_func(b);
}

无法编译:

error[E0308]: mismatched types
  --> src/main.rs:24:18
   |
24 |     consume_func(b);
   |                  ^ expected trait `Foo`, found trait `Foo + std::marker::Send`
   |
   = note: expected type `std::boxed::Box<std::boxed::Box<Foo + 'static>>`
              found type `std::boxed::Box<std::boxed::Box<Foo + std::marker::Send>>`

Boxa way to give a C library a void * pointer from Box<Trait>。由于指针过多,我无法将Box<Foo>转换为void *

我无法更改consume_func,而我不希望使用unsafe或其他分配。

2 个答案:

答案 0 :(得分:4)

这是一种方法:取消对b的引用(将其取消装箱到Box<Foo + Send>),然后立即将其包装在另一个Box<T>中,从而允许编译器进行推断正确的T(在本例中为Box<Foo>)。

consume_func(Box::new(*b));

之所以可行,是因为Box<Foo + Send>可以自动强制为Box<Foo>,而Box<Box<Foo + Send>>不能强制为Box<Box<Foo>>

答案 1 :(得分:2)

尽管您已经声明无法更改consume_func,但其他存在类似问题的人也可以将其更改为接受通用名称:

fn consume_func<F: Foo + ?Sized>(b: Box<Box<F>>) {
    unimplemented!();
}