首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rust克隆闭包预期的闭包,发现不同的闭包

Rust克隆闭包预期的闭包,发现不同的闭包
EN

Stack Overflow用户
提问于 2019-10-04 02:29:03
回答 1查看 195关注 0票数 0

我尝试将多个闭包传递给一个结构,并将它们存储为盒装的特征对象。这些闭包被包装在线程安全(Send,Sync)和可克隆(Clone)结构中。

代码语言:javascript
复制
use std::thread;

// make trait alias
trait SafeFnMut: FnMut() + Send + Sync {}
impl<F> SafeFnMut for F where F: FnMut() + Send + Sync {}

#[derive(Clone, Debug)]
struct WithCall<F> where F: Sized {
    fp: Box<F>,
}

impl<F> WithCall<F> where F: SafeFnMut {
    // boxing the closure here
    pub fn new(fp: F) -> Self {
        WithCall { fp: Box::new(fp) }
    }

    pub fn run(&mut self) {
        (self.fp)()
    }
}

struct HasWithCall<T> where T: SafeFnMut {
    pub first_fn: Option<Box<WithCall<T>>>,
    pub second_fn: Option<Box<WithCall<T>>>,
}

fn main() {
    let mut first_fn = WithCall::new(|| {
        println!("Called!")
    });

    let mut second_fn = WithCall::new(|| {
        println!("Called other!")
    });

    let has_with_call = HasWithCall {
        first_fn: Some(Box::new(first_fn.clone())),
        second_fn: Some(Box::new(second_fn.clone()))
    };

    println!("{:?}", first_fn.run());

    let mut first_fn_a = first_fn.clone();
    let mut first_fn_b = first_fn;

    let a = thread::spawn(move || {
        println!("In remote thread: {:?}", first_fn_a.run());
    });

    let b = thread::spawn(move || {
        println!("In remote thread: {:?}", first_fn_b.run());
    });

    a.join().expect("Thread A panicked");
    b.join().expect("Thread B panicked");
}

这段代码给出了以下错误:

代码语言:javascript
复制
error[E0308]: mismatched types   --> src/main.rs:39:34
second_fn: Some(Box::new(second_fn.clone()))                   
                         ^^^^^^^^^^^^^^^^^ expected closure, found a different closure

note: expected type `WithCall<[closure@src/main.rs:29:38: 31:6]>`
              found type `WithCall<[closure@src/main.rs:33:39: 35:6]>`

note: no two closures, even if identical, have the same type

help: consider boxing your closure and/or using it as a trait object

我为线程安全闭包引用了this question,为闭包类型错误引用了this question

我看到还有其他选项,比如对特征对象或函数指针的引用。不过,我想像上面写的那样,使用盒装的特征对象来解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-04 03:40:17

之所以会出现Expected closure, found a different closure中的错误消息,是因为Vec<T>只能包含一个具体类型T的闭包。在您的例子中,添加第二个类型参数U看起来更容易,这样您就可以拥有两个不同类型的不同闭包:

代码语言:javascript
复制
struct HasWithCall<T, U>
where
    T: SafeFnMut,
    U: SafeFnMut,
{
    pub first_fn: Option<Box<WithCall<T>>>,
    pub second_fn: Option<Box<WithCall<U>>>,
}

(full example)

顺便说一句,额外的Box对我来说似乎没有必要;使用Option<WithCall<T>>可能就足够了,因为WithCall中有一个Box

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58224969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档