-
Notifications
You must be signed in to change notification settings - Fork 2
ModuleSet
View the code in the repository
When you have a system that consists of polymorphic modules that each take care of their sub-section of the system you might run into the following: Every module has an inherited virtual API in common, from the base type that needs to be invoked for all modules. At the same time every module carries distinct functionality specialization with their own API extensions to manage this. In such situations one usually needs manual management of the separate instances to invoke the specific APIs whilst at the same time being able to invoke the generic API. It is this manual managing which this class aims to get rid of.
Note: This class is only applicable in the case where a system is comprised out of several polymorphic modules of which there exists only one instance of each.
Let us first define some polymorphic modules.
class TextPrinter
{
public:
TextPrinter(const std::string& text): mText(text) {}
virtual ~TextPrinter() {}
virtual void printStuff() const = 0;
protected:
std::string mText;
};
class MultiPrinter: public TextPrinter
{
public:
MultiPrinter(const std::string& text, int32_t amount):
TextPrinter::TextPrinter(text),
mAmount(amount) {}
virtual void printStuff() const
{
for(int32_t i = 0; i < mAmount; i++)
std::cout << mText << " ";
std::cout << "\n";
}
void setAmount(int32_t amount)
{
mAmount = amount;
}
private:
int32_t mAmount;
};
class WrapPrinter: public TextPrinter
{
public:
WrapPrinter(const std::string& text, const std::string& pattern):
TextPrinter::TextPrinter(text),
mPattern(pattern) {}
virtual void printStuff() const
{
std::cout << mPattern << mText << mPattern << "\n";
}
private:
std::string mPattern;
};
We can now declare our module set and add our modules.
th::ModuleSet<TextPrinter> modules; //supply the base type
//arguments are forwarded and the modules are created internally and owned by the ModuleSet
modules.emplace<MultiPrinter>("I am multiprinter!", 4);
modules.emplace<WrapPrinter>(WrapPrinter("I am wrap printer!", "xX!Xx"));
To perform generic operations that apply to all the contained modules, we can use this syntax:
modules.onEach([] (TextPrinter& printerModule)
{
printerModule.printStuff();
});
When we need to access the API specific to each module, we can retrieve the instances and the ModuleSet gives us the right object.
modules.get<MultiPrinter>().setAmount(5); //direct get which assumes that the module exists
WrapPrinter* wrapPrinter = modules.find<WrapPrinter>(); //returns nullptr if the module does not exist
This example prints:
xX!XxI am wrap printer!xX!Xx
I am multiprinter! I am multiprinter! I am multiprinter! I am multiprinter!