netxsimdg
Loading...
Searching...
No Matches
Module.hpp
Go to the documentation of this file.
1
8#ifndef MODULE_HPP
9#define MODULE_HPP
10
13
14#include <functional>
15#include <list>
16#include <map>
17#include <memory>
18#include <stdexcept>
19#include <string>
20
21namespace Module {
22
23template <typename I> std::unique_ptr<I> getInstance();
24
25template <typename I> I& getImplementation();
26
27template <typename I> void setImplementation(const std::string&);
28
29template <typename Int, typename Imp> std::unique_ptr<Int> newImpl()
30{
31 return std::unique_ptr<Int>(new Imp);
32}
33
34template <typename I, typename M> I& getImplTemplate() { return M::getImplementation(); }
35
36template <typename M> void setImplTemplate(const std::string& implName)
37{
38 M::setImplementation(implName);
39}
40
41template <typename I, typename M> std::unique_ptr<I> getInstTemplate() { return M::getInstance(); }
42
43typedef std::list<Nextsim::ConfigurationHelp> OptionMap;
44typedef std::map<std::string, OptionMap> HelpMap;
45using ConfigType = Nextsim::ConfigurationHelp::ConfigType;
46
47template <typename I> HelpMap& getHelpRecursive(HelpMap& map, bool getAll);
48
49template <typename I> class Module {
50public:
51 typedef std::function<std::unique_ptr<I>()> fn;
52 typedef std::map<std::string, fn> map;
53
54 static void setExternalImplementation(fn generator)
55 {
56 spf = generator;
57 staticInstance = std::move(spf());
58 }
59
60 static void setImplementation(const std::string& implName)
61 {
62 // setExternalImplementation() holds the common functionality
63 try {
64 setExternalImplementation(functionMap.at(implName));
65 } catch (const std::out_of_range& oor) {
66 std::throw_with_nested(std::runtime_error(
67 "No implementation named " + implName + " found for Module " + moduleName()));
68 }
69 }
70
71 static std::unique_ptr<I> getInstance() { return spf(); }
72
73 static I& getImplementation() { return *staticInstance; }
74
75 static std::list<std::string> listImplementations()
76 {
77 std::list<std::string> keys;
78 for (auto entry : functionMap) {
79 keys.push_back(entry.first);
80 }
81 return keys;
82 }
83
84 static std::string implementation()
85 {
86 typedef std::unique_ptr<I>(fnType)();
87 // The name is not cached, so find the function in the map which
88 // corresponds to spf. The hairy code is derived from
89 // https://stackoverflow.com/a/35920804
90 for (auto entry : functionMap) {
91 if (*entry.second.template target<fnType*>() == *spf.template target<fnType*>()) {
92 return entry.first;
93 }
94 }
95 return ""; // spf should always be an entry in functionMap
96 }
97
98 static std::string moduleName();
99
100private:
101 static fn spf;
102 static std::unique_ptr<I> staticInstance;
103 static map functionMap;
104};
105
106template <typename I, typename M> void addToConfiguredModules()
107{
109 Module<I>::moduleName(), M::setImplementation, M::implementation);
110}
111
112template <typename I> std::string implementation() { return Module<I>::implementation(); }
113
114}
115#endif /* MODULE_HPP */
static void configureModule(const std::string &mod, const fn &setter, const ofn &getter)