1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
#include <iostream>
#include <memory>
#include <unordered_map>
#include <string>
struct LivingBeing {
std::string name;
LivingBeing() = default;
LivingBeing (const std::string& n) : name(n) {}
virtual ~LivingBeing() = default;
virtual void chooseAction() = 0;
};
struct Wizard : LivingBeing {
using LivingBeing::LivingBeing;
virtual void chooseAction() override {}
};
struct Monster : virtual LivingBeing {
using LivingBeing::LivingBeing;
virtual void chooseAction() override {std::cout << "Monster::chooseAction() called.\n";}
};
struct Wolf : virtual Monster {
using Monster::Monster;
virtual void chooseAction() override {std::cout << "Wolf::chooseAction() called.\n";}
};
struct SummonedMonsterStrategy {
struct Exemplar {};
LivingBeing* summonedMonster;
static std::unordered_map<std::string, SummonedMonsterStrategy*> prototypesMap;
SummonedMonsterStrategy (LivingBeing* monster) : summonedMonster(monster) {}
SummonedMonsterStrategy (Exemplar, const std::string& name) {insertInPrototypesMap (name, this);}
virtual ~SummonedMonsterStrategy() = default;
static const std::unordered_map<std::string, SummonedMonsterStrategy*>& getPrototypesMap() {return prototypesMap;}
virtual void execute() = 0;
static void insertInPrototypesMap (const std::string& tag, SummonedMonsterStrategy* strategy) {
prototypesMap.emplace (tag, strategy);
std::cout << "{" << tag << ", " << strategy << "} inserted in SummonedMonsterStrategy::prototypesMap." << std::endl;
}
};
std::unordered_map<std::string, SummonedMonsterStrategy*> SummonedMonsterStrategy::prototypesMap;
struct AttackEnemiesOfSummoner : SummonedMonsterStrategy {
static const AttackEnemiesOfSummoner prototype;
using SummonedMonsterStrategy::SummonedMonsterStrategy;
AttackEnemiesOfSummoner (Exemplar e) : SummonedMonsterStrategy (e, "Attack Enemies Of Summoner") {}
virtual void execute() override;
};
const AttackEnemiesOfSummoner AttackEnemiesOfSummoner::prototype (Exemplar{});
struct SummonedMonster : virtual Monster {
LivingBeing* summoner;
SummonedMonster (LivingBeing* s) : summoner(s) {}
};
template <typename T>
struct Summoned : SummonedMonster, T { // Adapter Pattern
std::shared_ptr<SummonedMonsterStrategy> summonedMonsterStrategy;
Summoned (LivingBeing* summoner, const std::string& name) : LivingBeing(name), SummonedMonster(summoner) {
summonedMonsterStrategy = std::make_shared<AttackEnemiesOfSummoner>(this);
}
// virtual void chooseAction() override {T::chooseAction();} // What I originally had, which worked, but fails to incorporte 'summonedMonsterStrategy'.
virtual void chooseAction() override {summonedMonsterStrategy->execute();} // This I want to use now.
};
void AttackEnemiesOfSummoner::execute() {
// summonedMonster->chooseAction(); // This creates an infinite loop back to itself.
dynamic_cast<Monster*>(summonedMonster)->Monster::chooseAction();
/* Would like to use 'T::chooseAction();' instead but since execute() is virtual it cannot get the template T.
SummonedMonsterStrategy itself can be a template class, but then the problem is
const AttackEnemiesOfSummoner AttackEnemiesOfSummoner::prototype (Exemplar{});
will have to change to
const AttackEnemiesOfSummoner<T> AttackEnemiesOfSummoner<T>::prototype (Exemplar{});
which won't be instantiated unless ALL
Monster subtypes are used for T, and there are too many of them (and too many derived types of SummonedMonsterStrategy too).*/
}
int main() {
Wizard wizard ("Wizard");
Summoned<Wolf> summonedWolf (&wizard, "Summoned Wolf");
summonedWolf.chooseAction(); // Monster::chooseAction() called.
}
// Want to have "Wolf::chooseAction() called." to be the output though.
|