避免结构中的PhantomData强制执行类型约束(Avoiding PhantomData in a struct to enforce type constraints)

编程入门 行业动态 更新时间:2024-10-22 23:45:15
避免结构中的PhantomData强制执行类型约束(Avoiding PhantomData in a struct to enforce type constraints)

我正在尝试开发一种批处理系统。 在那里我想使用某种Process结构,它拥有所有与流程相关的部分。 当前的实现使用PhantomData来强制执行类型约束:

pub struct Process<P: Producer<U>, T: Transformer<U, V>, C: Consumer<V>, U,V> { producer: P, transformer: T, consumer: C, p1: PhantomData<U>, p2: PhantomData<V>, }

这个想法是由Producer发出的类型将被Transformer (可能是另一种类型)使用,并由Consumer 。 因此类型必须匹配。

Process结构应该拥有实现Producer , Transformer和Consumer特性的项目。 我想这就是为什么我需要使用类型参数。 因为我不能直接使用这个特质

... producer: Producer<U>, ...

因为编译时未知的大小。

有没有更好的方法来做到这一点? 我对Rust很新,所以我可能会在错误的方向思考。

该解决方案有效,但对于那些PhantomData字段看起来有点奇怪。 也许这只是PhantomData的用途?

I'm trying to develop a kind of batch system. Within that I'd like to use some kind of Process struct, which owns all process related parts. The current implementation uses PhantomData to enforce the type constraints:

pub struct Process<P: Producer<U>, T: Transformer<U, V>, C: Consumer<V>, U,V> { producer: P, transformer: T, consumer: C, p1: PhantomData<U>, p2: PhantomData<V>, }

The idea is that type emitted by the Producer will be used by the Transformer (maybe to a different type) and consumed by the Consumer. Therefore the types must match.

The Process struct should own the items implementing the Producer, Transformer and Consumer traits. I think that's why I need to use type parameters. Since I cannot use the the trait directly like

... producer: Producer<U>, ...

because of the unknown size at compile time.

Is there a better way of doing this? I'm pretty new to Rust, so I might be thinking in the wrong direction.

The solution works, but it looks a bit odd with those PhantomData fields. Maybe that is just what PhantomData is used for?

最满意答案

您需要关联的类型而不是类型参数:

trait Producer { type Output; fn produce(&self) -> Self::Output; } trait Transformer { type Input; type Output; fn transform(&self, val: Self::Input) -> Self::Output; } trait Consumer { type Input; fn consume(&self, val: Self::Input); } struct Process<P, T, C> where P: Producer, T: Transformer<Input = P::Output>, C: Consumer<Input = T::Output> { producer: P, transformer: T, consumer: C, } impl<P, T, C> Process<P, T, C> where P: Producer, T: Transformer<Input = P::Output>, C: Consumer<Input = T::Output> { fn run(&self) { let a = self.producer.produce(); let b = self.transformer.transform(a); self.consumer.consume(b); } } struct MakeNum; impl Producer for MakeNum { type Output = u8; fn produce(&self) -> u8 { 41 } } struct AddOne; impl Transformer for AddOne { type Input = u8; type Output = u8; fn transform(&self, val: u8) -> u8 { val + 1 } } struct PrintNum; impl Consumer for PrintNum { type Input = u8; fn consume(&self, val: u8) { println!("Value was {}", val) } } fn main() { let process = Process { producer: MakeNum, transformer: AddOne, consumer: PrintNum, }; process.run(); }

虽然我通常不会在struct本身中添加where子句,但我只是在impl上添加where子句,它也会有一个确保约束的new方法。

Instead of type parameters, you want associated types:

trait Producer { type Output; fn produce(&self) -> Self::Output; } trait Transformer { type Input; type Output; fn transform(&self, val: Self::Input) -> Self::Output; } trait Consumer { type Input; fn consume(&self, val: Self::Input); } struct Process<P, T, C> where P: Producer, T: Transformer<Input = P::Output>, C: Consumer<Input = T::Output> { producer: P, transformer: T, consumer: C, } impl<P, T, C> Process<P, T, C> where P: Producer, T: Transformer<Input = P::Output>, C: Consumer<Input = T::Output> { fn run(&self) { let a = self.producer.produce(); let b = self.transformer.transform(a); self.consumer.consume(b); } } struct MakeNum; impl Producer for MakeNum { type Output = u8; fn produce(&self) -> u8 { 41 } } struct AddOne; impl Transformer for AddOne { type Input = u8; type Output = u8; fn transform(&self, val: u8) -> u8 { val + 1 } } struct PrintNum; impl Consumer for PrintNum { type Input = u8; fn consume(&self, val: u8) { println!("Value was {}", val) } } fn main() { let process = Process { producer: MakeNum, transformer: AddOne, consumer: PrintNum, }; process.run(); }

Although I wouldn't normally add the where clause on the struct proper, I'd just have it on the impl which would also have a new method that ensures the constraints just as well.

更多推荐

本文发布于:2023-08-05 08:06:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1430212.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:强制执行   类型   结构   PhantomData   Avoiding

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!