Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Design problem for programmers SE
#include <iostream>
#include <map>
#include <boost/any.hpp>
enum class eInput {
ONE, TWO, THREE
};
// are a string, a double and an int
enum class eOutput {
SPAM, HAM, EGGS
};
// are a string, a double and an int
using InputMap = std::map<eInput, boost::any>;
using OutputMap = std::map<eOutput, boost::any>;
class PluginBase
{
public:
virtual void Evaluate(InputMap& inputs, OutputMap& outputs) = 0;
virtual InputMap GetInputs(OutputMap& outputs) = 0;
};
class PluginA : public PluginBase
{
public:
void Evaluate(InputMap& inputs, OutputMap& outputs) override
{
for(auto& out : outputs)
{
switch(out.first)
{
case eOutput::SPAM:
out.second = "Hello "
+ boost::any_cast<std::string>(inputs.at(eInput::ONE))
+ std::to_string(boost::any_cast<int>(inputs.at(eInput::THREE)));
break;
default:
throw std::runtime_error("This Plugin can't handle anything besides SPAM");
}
}
}
InputMap GetInputs(OutputMap& outputs) override
{
InputMap inputs;
for (auto& out : outputs)
{
switch(out.first)
{
case eOutput::SPAM:
inputs[eInput::ONE];
inputs[eInput::THREE];
break;
default:
throw std::runtime_error("This Plugin can't handle anything besides SPAM");
}
}
return inputs;
}
};
class PluginB : public PluginBase
{
public:
void Evaluate(InputMap& inputs, OutputMap& outputs) override
{
for(auto& out : outputs)
{
switch(out.first)
{
case eOutput::HAM:
out.second = 2.0*boost::any_cast<double>(inputs.at(eInput::TWO));
break;
case eOutput::EGGS:
out.second = 4 + boost::any_cast<int>(inputs.at(eInput::THREE));
break;
default:
throw std::runtime_error("This Plugin can't handle anything besides HAM & EGGS");
}
}
}
InputMap GetInputs(OutputMap& outputs) override
{
InputMap inputs;
for (auto& out : outputs)
{
switch(out.first)
{
case eOutput::HAM:
inputs[eInput::TWO];
break;
case eOutput::EGGS:
inputs[eInput::THREE];
break;
default:
throw std::runtime_error("This Plugin can't handle anything besides HAM & EGGS");
}
}
return inputs;
}
};
class Handler
{
public:
Handler(PluginBase* rPlugin) : plugin(rPlugin) {}
void ShowOutputs(OutputMap& outputs)
{
InputMap inputs = plugin->GetInputs(outputs);
for (auto& in : inputs)
{
switch(in.first)
{
case eInput::ONE:
in.second = std::string("World");
break;
case eInput::TWO:
in.second = 43.0;
break;
case eInput::THREE:
in.second = 5;
break;
default:
throw std::runtime_error("Can't handle this input.");
}
}
plugin->Evaluate(inputs, outputs);
for (auto& out : outputs)
{
switch(out.first)
{
case eOutput::SPAM:
std::cout << boost::any_cast<std::string>(out.second) << std::endl;
break;
case eOutput::HAM:
std::cout << boost::any_cast<double>(out.second) << std::endl;
break;
case eOutput::EGGS:
std::cout << boost::any_cast<int>(out.second) << std::endl;
break;
default:
throw std::runtime_error("Can't show this output.");
}
}
}
private:
PluginBase* plugin;
};
int main()
{
PluginA pluginA;
Handler handler(&pluginA);
OutputMap outputs;
outputs[eOutput::SPAM];
handler.ShowOutputs(outputs);
PluginB pluginB;
Handler handler2(&pluginB);
OutputMap outputs2;
outputs2[eOutput::HAM];
handler2.ShowOutputs(outputs2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment