My colleagues and I are struggling with a design problem. I'll try and explain the situation:
We have a number of different components (let's call them plugins), that take an input, do something with it, and give an output back. Each plugin takes a different number (and different types of) inputs, and gives back a different number (and different types of) outputs. Some of the inputs and outputs overlap, meaning that one output can be calculated by several plugins and one input may be needed by several plugins. On top of that, we have some "meta-plugins" that combine similar inputs or outputs of several plugins.
And we have a class that is tasked with calling a plugin, let's call that a handler, but it doesn't know which one, only that it is a plugin. Unfortunately, the inputs and outputs have almost nothing to do with each other, and can't really be treated polymorphically.
What we are doing right now, is putting the in-and outputs in heterogeneous maps, keyed with an enum. The handler calls PluginBase::Evaluate(inputmap, outputmap) on the derived plugin object, and the object goes to work. But now the plugins needs to iterate over the map, see which of the in- and outputs it can actually work with. Also, there is a lot of casting involved, as you might imagine by now.
Ideally, the plugins would each have a sane interface for the work, e.g.
double PluginA::GetHam(double x); std::string PluginB::GetSpam(int x, int y);
but then the handler would not be able to work with them.
I've created a compileable example of what we're doing right now, but beware, it's exactly as horrible as you think it is.
Edit: Maybe this is a better way to think of it: The handler has various data, your input data. So let's say you want a behaviour that, if request eOutput::HAM, it gives you three times eInput::TWO. You implement a plugin Thrice, and give it the required in- and output maps. You can change how you get from TWO (or any other combination of eInputs) to HAM by implementing your own plugin, but you don't have the input data to get to HAM without the handler.