繁体   English   中英

如何编写接受特征或指向特征的智能指针(Box、Rc 等)的通用代码?

[英]How do I write generic code that accepts either a trait or a smart pointer to the trait (Box, Rc, etc)?

我正在编写一个离散事件模拟器来模拟流程,交换事件。 进程是特征进程的实现,并存储在模拟类中,它告诉它们何时处理事件。

模拟可以只包含一种类型的进程,也可以包含不同类型的进程。 这就是为什么我需要能够自由选择动态流程的原因。

我目前用盒子来做。 使用模拟的每个代码都需要创建框并将其创建的对象放入框中。

trait Process {
    // methods
    fn start();
    fn process_event();
}

struct Simulation {
    processes: Vec<dyn Process>
}

impl Simulation {
    fn add_process(&mut self, p: Box<dyn Process>) {
        processes.push(p);
    }
    
    fn run() {
        // calls process_event on processes, based on simulation logic
    }
}

我最大的问题是,在某些情况下,这些过程需要有自引用。 然后我需要用 Pin 或 OwningRef 替换 box,并且我不想进行所有可能的模拟,创建 Pin 或 OwningRef。 所以,我想要某种通用参数来告诉模拟为盒子使用不同的类。

一个很好的扩展是完全没有动态调度,并且模拟包含实际的流程类型,而不是泛型。

所以,我想要类似 - Simulation<P> where P is either a Process or Deref<Process>东西Simulation<P> where P is either a Process or Deref<Process>

通用Simulation两种变体都是可能的。

  1. 包含指向进程的智能指针( playground ):
trait Process {}
struct P {}
impl Process for P {}

struct Simulation<T: std::ops::Deref<Target = dyn Process> + Sized> {
    processes: Vec<T>
}

impl<T: std::ops::Deref<Target = dyn Process> + Sized> Simulation<T> {
    fn add_process(&mut self, p: T) {
        self.processes.push(p);
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation<Box<dyn Process>> = Simulation { processes: vec![] };
    s.add_process(Box::new(P {}));
    s.run();
    
    let mut s: Simulation<std::rc::Rc<dyn Process>> = Simulation { processes: vec![] };
    s.add_process(std::rc::Rc::new(P {}));
    s.run();
}
  1. 包含实际流程类型( playground ):
trait Process {}
struct P {}
impl Process for P {}

struct P2 {}
impl Process for P2 {}

struct Simulation<T: Process> {
    processes: Vec<T>
}

impl<T: Process> Simulation<T> {
    fn add_process(&mut self, p: T) {
        self.processes.push(p);
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation<P> = Simulation { processes: vec![] };
    s.add_process(P {});
    s.run();
    
    let mut s: Simulation<P2> = Simulation { processes: vec![] };
    s.add_process(P2 {});
    s.run();
}
  1. 您甚至可以拥有一种类型的模拟,其中包含不同类型的流程 ( playground ):
trait Process {}
struct P {}
impl Process for P {}

struct P2 {}
impl Process for P2 {}

struct Simulation {
    processes: Vec<Box<dyn Process>>
}

impl Simulation {
    fn add_process<T: Process + 'static>(&mut self, p: T) {
        self.processes.push(Box::new(p));
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation = Simulation { processes: vec![] };
    s.add_process(P {});
    s.run();
    
    let mut s: Simulation = Simulation { processes: vec![] };
    s.add_process(P2 {});
    s.run();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM