考虑这样的代码:
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>>`
双Box
是a way to give a C library a void *
pointer from Box<Trait>
。由于指针过多,我无法将Box<Foo>
转换为void *
。
我无法更改consume_func
,而我不希望使用unsafe
或其他分配。
答案 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!();
}