I have an abstract class in C++ with several subclasses.
Is it somehow by Macros or template metaprogramming possible to do something like that:
foreach subclass of Base:
mymap[subclass::SOME_CONSTANT] = new subclass();
No, you cannot.
What you want, apparently, is a Factory
(or perhaps Abstract Factory
).
In C++, you setup a Factory class and register builders.
class FooFactory
{
public:
typedef std::function<Foo*()> Builder;
/// returns true if the registration succeeded, false otherwise
bool Register(std::string const& key, Builder const& builder) {
return map.insert(std::make_pair(key, builder)).second;
}
/// returns a pointer to a new instance of Foo (or a derived class)
/// if the key was found, 0 otherwise
Foo* Build(std::string const& key) const {
auto it = _map.find(key);
if (it == _map.end()) { return 0; } // no such key
return (it->second)();
}
private:
std::map<std::string, Builder> _map;
};
You can create a singleton of this factory, to register the derived classes during library load, which is handy for plugins-like architecture:
FooFactory& GetFooFactory() { static FooFactory F; return F; }
And you can prepare a handy builder:
template <typename Derived>
Foo* fooBuilder() { return new Derived(); }
Then people are expected to register their derived classes in the factory:
static const bool registeredBar =
GetFooFactory().Register("Bar", fooBuilder<Bar>);
Note: it is far from being mandatory that the factory should be a singleton, though it's not as evil here because it's constant once the load of the libraries ends.
Note: for a proper plugin architecture, you'd need to use RAII (instead of a bool), to handle the unregistration at library unload. It's much rarer though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With