Ржавчина клонировала укупорки, ожидала закрытия, нашла разные закрытия - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь передать несколько замыканий в структуру и сохранить их как объекты в штучной упаковке. Эти замыкания заключены в многопотоковую (Send, Sync) и клонируемую (Clone) структуру.

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");
}

Этот код выдает мне следующую ошибку:

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

I этот вопрос для потоковых безопасных замыканий и этот вопрос для ошибки типа замыкания.

Я вижу, что есть и другие варианты, такие как ссылка напризнак объекта или указатель на функцию. Тем не менее, я хотел бы решить эту проблему с помощью объекта в штучной упаковке, как я уже писал выше.

1 Ответ

1 голос
/ 03 октября 2019

Сообщение об ошибке в Ожидаемое закрытие, обнаружено другое закрытие происходит потому, что Vec<T> может содержать замыкания только одного конкретного типа T. В вашем случае проще добавить параметр второго типа U, чтобы можно было хранить два разных замыкания разных типов:

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

( полный пример )

Как примечание, дополнительный Box кажется мне ненужным;вероятно, достаточно использовать Option<WithCall<T>>, поскольку внутри WithCall есть Box.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...