Alors, pour un projet perso, j'ai besoin d'une factory dans un cadre de polymorphisme. J'ai donc quelque chose comme :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Format {}; // Il manque tous les tests et les exceptions en cas d'erreur, mais l'idée est là. class Factory { typedef unique_ptr<Format> (*format_creator_t) (); typedef std::unordered_map<std::string, format_creator_t> format_map_t; public: static Factory formats() { static format_map_t map; return map; } static bool reg(const std::string& key, format_creator_t val) { auto map = formats(); map.emplace(key, val); return true; } static unique_ptr<Format> get(const std::string& key) { auto map = formats(); return map[key](); } }; |
Là dessus, j'aimerai bien que chaque format s'enregistre de lui-même dans la factory, sans que l'utilisateur n'ai besoin de le faire au début de son main
. J'ai une variable de classe statique dans chaque pair .hpp/.cpp
, qui se charge d'enregistrer mon Format.
1 2 3 4 5 6 7 8 9 10 | class FormatA : public Format { public: // ... private: static bool registered; }; static bool FormatA::registered = Factory::reg("format_a", [](){ return std::unique_ptr<Format>(new FormatA()); }); |
Si vous voulez voir le code en vrai, la factory est là, et un exemple de format ici et là
Seulement, ce code m'oblige à utiliser une bibliothèque partagée, pour que les symboles correspondant ne soit pas supprimés par le linker, et que mes formats soit bien enregistré à l'initialisation de la bibliothèque.
Je me demandais donc s'il pouvait y avoir une autre astuce en C++ pour gérer ce genre de cas, et me permettre de proposer une bibliothèque statique à mes utilisateur. Toutes les implémentations de Factory que j'ai vu çà ce jour utilisent un enregistrement dans le main
de l'appelant.
Une solution serait d'avoir une fonction init_formats
, que l'utilisateur se charge appeler au début de son utilisation, et qui effectue cet enregistrement. Seulement, cela me force à mettre à jour le code de cette fonction à chaque ajout de format, au lieu d'avoir simplement une ligne en bas du .cpp correspondant au format. Ces deux points me gênent un peu.