gpt4 book ai didi

rust - 将结构转换为特征

转载 作者:行者123 更新时间:2023-12-03 11:42:20 27 4
gpt4 key购买 nike

我正在尝试实现一个队列,在此队列中,生产者可以在其中添加实现QueueTrait的结构,并在出队时将在不同的线程上调用trait的invoke方法。由于出现以下错误,因此无法编译:

self.queue.enqueue(self.data);
^^^^^^^^^ expected trait object `dyn QueueTrait`, found struct `ProducerData`

expected struct `std::sync::Arc<std::boxed::Box<dyn QueueTrait + std::marker::Send>>`
found struct `std::sync::Arc<std::boxed::Box<ProducerData>>
是否可以将ProducerData强制转换为QueueTrait?有什么方法可以避免将Producer完全拆分为ProducerData并将其本身添加到队列中吗?
use std::collections::VecDeque;
use std::sync::{Arc, Condvar, Mutex};
use std::thread;

pub struct Queue<'a> {
items: Mutex<VecDeque<Arc<Box<dyn QueueTrait + Send + 'a>>>>,
condvar: Condvar,
}

impl<'a> Queue<'a> {
pub fn new() -> Self {
Self {
condvar: Condvar::new(),
items: Mutex::new(VecDeque::new()),
}
}

pub fn enqueue(&self, qt: Arc<Box<dyn QueueTrait + Send + 'a>>) {
self.items.lock().unwrap().push_back(qt);
self.condvar.notify_one();
}

fn dequeue(&self) -> Arc<Box<dyn QueueTrait + Send + 'a>> {
let mut q = self.items.lock().unwrap();

while q.is_empty() {
q = self.condvar.wait(q).unwrap();
}

q.pop_front().unwrap()
}

pub fn dispatch(&self) {
loop {
let qt = self.dequeue();
qt.invoke();
}
}
}

struct ProducerData {
invoke_count: Mutex<u32>
}

struct Producer {
queue: Arc<Queue<'static>>,
data: Arc<Box<ProducerData>>
}

impl Producer {
fn new(queue: Arc<Queue<'static>>) -> Self {
Self { queue, data: Arc::new(Box::new(ProducerData{ invoke_count: Mutex::new(0)}) ) }
}

fn produce(&self) {
self.queue.enqueue(self.data);
}
}

pub trait QueueTrait {
fn invoke(&self);

fn as_trait(&self) -> &dyn QueueTrait;
}

impl QueueTrait for ProducerData {
fn invoke(&self) {
self.invoke_count.lock().unwrap() +=1;
println!("Invoke called!")
}

fn as_trait(&self) -> &dyn QueueTrait {
self as &dyn QueueTrait
}
}

fn main() {
let q = Arc::new(Queue::new());
let p1 = Producer::new(Arc::clone(&q));

// Consumer thread
let c = thread::Builder::new().name("consumer".to_string()).spawn(move
|| q.dispatch() ).unwrap();

// Produce on main thread
p1.produce();

c.join().unwrap();
}

最佳答案

您已经在as_trait中使用了强制转换,但只是为了使其更清晰。可以使用as关键字将对象强制转换为特征:

use std::sync::Arc;

struct MyStruct;

trait MyTrait {}

impl MyTrait for MyStruct {}

fn main() {
let my_struct: MyStruct = MyStruct;

// behind a reference
let trait_object: &dyn MyTrait = &MyStruct as &dyn MyTrait;

// behind a box
let trait_object: Box<dyn MyTrait> = Box::new(MyStruct) as Box<dyn MyTrait>;

// behind an Arc
let trait_object: Arc<dyn MyTrait> = Arc::new(MyStruct) as Arc<dyn MyTrait>;

// behind an Arc Box
// DOESN'T COMPILE!
let trait_object: Arc<Box<dyn MyTrait>> = Arc::new(Box::new(MyStruct)) as Arc<Box<dyn MyTrait>>;
}
但这在两个间接指令(例如 ArcBox)之后不起作用。
您的整个设置对我来说似乎太复杂了。正如@kmdreko所指出的,仅使用 Arc似乎有效。您应该重新考虑程序要做什么,并考虑一种更简单的方法。

关于rust - 将结构转换为特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66295113/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com