I am using the factory pattern. It basically allows classes to be registered at compile time and stored in a map. An instance can then be returned using BaseFactory::createInstance()
I am not sure how a map is holding class names at compile time !! How can memory be allocated in compile time that’s valid at run time ?
All class is in this case is derived from the parent class Bump_BaseObject
//C++ STL used for adding Reflection
#include <string>
#include <map>
class Bump_BaseObject;
/**
* Derived Base objects creation factory
*/
template<typename T>
Bump_BaseObject* createT(void)
{
#pragma message("createT instantiated")
return new T();
}
struct BaseFactory {
typedef std::map<std::string, Bump_BaseObject*(*)()> map_type;
//return an instance of the class type 's'
static Bump_BaseObject* createInstance(const std::string& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return 0;
//this is where we instatiate and allocate memory for the object(it must NOT have any arguments)
//we could write a variant that accepts args, but there is no need.
return it->second();
}
//check if 's' is present in the map of registered types
static bool checkIfRegisteredType(const std::string& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return false;
return true;
}
protected:
static map_type* getMap() {
// never delete'ed. (exist until program termination)
// because we can't guarantee correct destruction order
if(!objectMap) { objectMap = new map_type; }
return objectMap;
}
private:
static map_type * objectMap;
};
#define VALUE_TO_STRING(x) #x
template<typename T>
struct DerivedRegister : BaseFactory {
DerivedRegister(const std::string& s) {
#pragma message("Type registered")
getMap()->insert(std::pair<std::string, Bump_BaseObject*(*)()>(s, &createT<T>));
}
};
Also is there a way to print the class names as they get registered ?
I think your code is altogether confused, mixing preprocessor directives with strange inheritance patterns. Instead of trying to fix it, I’d like to present a generic, self-registering factory framework (which will print out registrations as they happen).
Note that all global initialization happens during the dynamic initialization phase, i.e. at runtime just before
main()is called.Base.hpp:
Base.cpp:
Usage Example
Example.hpp:
Example.cpp:
Main.cpp
The crux here is that each derived class has a static
Registrarmember, which gets initialized (in unspecified order) during the dynamic initialization phase of your program, and each constructor of which performs the actual insertion into the registry map, as well as printing out of the log message.(If you don’t have a modern C++ compiler, you would have to use the old C++98-style syntax:)