避免在结构中使用PhantomData来强制执行类型约束

时间:2015-10-29 08:45:30

标签: rust

我正在尝试开发一种批处理系统。在其中,我想使用某种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结构应该拥有实现ProducerTransformerConsumer特征的项目。我认为这就是我需要使用类型参数的原因。因为我不能像

那样直接使用这个特性
...
producer: Producer<U>,
...

因为编译时的大小未知。

有更好的方法吗?我对Rust很陌生,所以我可能会在错误的方向思考。

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

1 个答案:

答案 0 :(得分:8)

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

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

虽然我通常不会在where上添加struct条款,但我只能在impl上使用new方法这也确保了约束。