0

I'm building program that will take circuit of logical gates and evaluate the circuit. I made trait for a logical gate which has methods to get the output value and register and unregister inputs (parents).

pub trait LogicalGate {
    fn register_input<T: LogicalGate>(&mut self, input: &T) -> Result<(), LogicalGateError>;
}

T in this method is any logical gate implementation.

Now, I want to implement a gate that will take one parent and return it's output. However, I have troubles storing the parent as I don't know what the type of OutputGate::parent should be:

pub struct OutputGate<'a> {
    parent: &'a dyn LogicalGate,
}

impl<'a> LogicalGate for OutputGate {
    // ...
}

I want to be able to store any T: LogicalGate there. I can't make the whole OutputGate structure generic as I will want to be able to put multiple different structures (that all implement LogicalGate) into one Vec in the future.

No matter if I try &'a dyn LogicalGate or Box<LogicalGate>, the compiler complains that LogicalGate cannot be made into an object, as it contains generic type parameters.

How can I make a field in a struct that can take any type T that implements a certain trait, which contains a method that adds any type T into the field in struct?

In C#, I would do it like this:

public interface ILogicalGate {
     void RegisterInput(ILogicalGate input);
}

public class OutputGate : ILogicalGate {
    private ILogicalGate parent;
    public void RegisterInput(ILogicalGate input) { parent = input; }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
SoptikHa
  • 437
  • 4
  • 19
  • It looks like your question might be answered by the answers of [What is the cited problem with using generic type parameters in trait objects?](https://stackoverflow.com/q/57252674/155423); [How do I create a heterogeneous collection of objects?](https://stackoverflow.com/q/27957103/155423); . If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Nov 08 '19 at 21:11
  • Your C# example uses dynamic dispatch for the argument; do the same thing here. – Shepmaster Nov 08 '19 at 21:17
  • Thank you, these links answered my question, apparently I suck at googling. Feel free to mark this as duplicate, thanks for sharing the answers beforehand. It looks like the best way to implement this is plain enum. – SoptikHa Nov 08 '19 at 21:26
  • Nah, I have a broad knowledge of what Q&A already exist, so it's very easy for me to find existing questions quickly. – Shepmaster Nov 08 '19 at 21:28
  • 1
    [This is how I'd write the equivalent dynamic dispatch version](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9254b84750bc68454bf3f5abc0cffd09), based on the code you've provided. – Shepmaster Nov 08 '19 at 21:29
  • Oh. Okay, that's way better than enums. Thanks very much, this helps me a lot. – SoptikHa Nov 08 '19 at 22:06

0 Answers0