代码之家  ›  专栏  ›  技术社区  ›  Makogan

如何调用存储在Box中的dyn函数?

  •  0
  • Makogan  · 技术社区  · 2 年前

    我有这样的片段:

    use std::sync::{Arc, Mutex};
    
    pub struct TaskGroup
    {
        task_group: Arc<Mutex<Box<dyn Fn() -> dyn Iterator<Item=usize>>>>,
    }
    
    impl TaskGroup
    {
        fn foo(&self)
        {
            for task in self
                    .task_group
                    .lock()
                    .unwrap()()
            {}
        }
    }
    

    返回:

    error[E0618]: expected function, found `MutexGuard<'_, Box<(dyn Fn() -> (dyn Iterator<Item = task::TaskHandle> + 'static) + 'static)>>`
      --> crates/thread_pool/src/task.rs:60:25
       |
    60 |               for task in self // task
       |  _________________________^
    61 | |                 .post_reqs // RwLock
    62 | |                 .read() // handle
    63 | |                 .unwrap() // Ref to TaskGroup
    64 | |                 .task_group // TaskGroup
    65 | |                 .lock()// Mutex lock
    66 | |                 .unwrap()()
       | |_________________________^ this trait object returns an unsized value `(dyn Iterator<Item = task::TaskHandle> + 'static)`, so it cannot be called
    

    那么,调用框中的函数并获得迭代器的正确方法是什么呢?

    1 回复  |  直到 2 年前
        1
  •  2
  •   vallentin Remi    2 年前

    问题与以下内容不起作用的原因相同:

    fn f() -> dyn Iterator<Item = usize> {
        0..10
    }
    

    您试图返回的内容的大小在编译时未知。如果是常规的 fn ,然后您可以替换 dyn 具有 impl (or return position impl trait) 一切都会好起来的。然而,由于您处理的是闭包,所以事情会变得有点复杂。你需要把它装箱。

    use std::sync::{Arc, Mutex};
    
    let f: Arc<Mutex<Box<dyn Fn() -> Box<dyn Iterator<Item = usize>>>>> =
        Arc::new(Mutex::new(Box::new(|| Box::new((0..10).into_iter()))));
    
    let mut guard = f.lock().unwrap();
    let f = guard.as_mut();
    
    for x in f() {
        println!("{}", x);
    }
    

    记得保存返回的警卫 .lock() 。否则,编译器将抱怨一个临时的在使用中被释放。

    推荐文章