A
是一个包含向量的结构B
. A
实施add_b
方法添加了一个B
实例到列表B
. B
包含一个闭包属性f
.
如果我添加一个B
到向量add_b
, 没关系。如果我将两个向量相加add_b
,我收到一个错误,说两个闭包不同。这是一个最小的例子:
// A struct...
struct A<F> {
b_vec: Vec<B<F>>, // A vector of B
}
// ...and its implementation
impl<F> A<F>
where
F: Fn(),
{
fn new() -> A<F> {
A { b_vec: Vec::new() }
}
fn add_b(&mut self, b: B<F>) {
self.b_vec.push(b);
}
}
// B struct...
struct B<F> {
f: F,
}
// ...and its implementation
impl<F> B<F>
where
F: Fn(),
{
fn new(f: F) -> B<F> {
B { f: f }
}
}
// I add two B (with their closures arguments) in A
fn main() {
let mut a = A::new();
a.add_b(B::new(|| println!("test")));
a.add_b(B::new(|| println!("test2")));
}
这段代码的结果是:
error[E0308]: mismatched types
--> src/main.rs:39:20
|
39 | a.add_b(B::new(|| println!("test2")));
| ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
如何添加多个B
与他们不同的关闭A
's b_vec
?
总是值得一看的full编译器输出:
error[E0308]: mismatched types
--> src/main.rs:39:20
|
39 | a.add_b(B::new(|| println!("test2")));
| ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
|
= note: expected type `[closure@src/main.rs:38:20: 38:39]`
found type `[closure@src/main.rs:39:20: 39:40]`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
特别有帮助:
-
no two closures, even if identical, have the same type
-
consider boxing your closure and/or using it as a trait object
我们可以通过删除类型来进一步简化您的示例B
共。那么唯一的任务就是保存一个闭包向量。正如编译器告诉我们的那样,没有两个闭包具有相同的类型,但是Vec
是同构数据结构,这意味着其中的每个项目都具有相同的类型。
我们可以通过引入一级间接来解决该限制。正如编译器所建议的,这可以通过特征对象或装箱来完成(后一种包括第一种)。相应的类型如下所示:
-
Vec<&dyn Fn()>
(参考特征对象)
-
Vec<Box<dyn Fn()>>
(盒子里的特征对象)
在你的例子中你想要own所有闭包,因此正确的选择是将所有闭包装箱,如Box<T>
是一个拥有的包装器,而引用只是借用东西。
一个完整的工作示例:
struct A {
b_vec: Vec<B>,
}
impl A {
fn new() -> A {
A { b_vec: Vec::new() }
}
fn add_b(&mut self, b: B) {
self.b_vec.push(b);
}
}
struct B {
f: Box<dyn Fn()>,
}
impl B {
fn new<F>(f: F) -> B
where
F: Fn() + 'static,
{
B { f: Box::new(f) }
}
}
fn main() {
let mut a = A::new();
a.add_b(B::new(|| println!("test")));
a.add_b(B::new(|| println!("test2")));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)