Factory pattern memory allocation at compile time and how to print compile time information

I am using a factory pattern. It basically allows you to register classes at compile time and save them on a map. Then the instance can be returned using BaseFactory :: createInstance ()

I'm not sure how the map stores class names at compile time !! How can memory be allocated at compile time that is valid at run time?

In this case, the entire class is inferred 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>));
    }
};

Is there also a way to print class names as they are registered?

+3
source share
1 answer

, , . , , factory ( ).

, , main().

Base.hpp:

#include <unordered_map>
#include <string>

class Base
{
public:
    typedef Base * (*base_creator_fn)();
    typedef std::unordered_map<std::string, base_creator_fn> registry_map;

    virtual ~Base() = default;

    static registry_map & registry();
    static Base * instantiate(std::string const & name);
};

struct Registrar
{
    Registrar(std::string name, Base::base_creator_fn func);
};

Base.cpp:

#include "Base.hpp"
#include <iostream>

registry_map & Base::registry()
{
    static registry_map impl;
    return impl;
}

Base * Base::instantiate(std::string const & name)
{
    auto it = Base::registry().find(name);
    return it == Base::registry().end() ? nullptr : (it->second)();
}

Registrar::Registrar(std::string name, Base::base_creator_fn func)
{
    Base::registry()[name] = func;
    std::cout << "Registering class '" << name << "'\n";
}

Example.hpp:

#include "Base.hpp"

class DerivedExample : public Base
{
    static Registrar registrar;
public:
    static Base * create() { return new DerivedExample; }
    // ...
};

Example.cpp:

#include "Example.hpp"

Registrar DerivedExample::registrar("DerivedExample", DerivedExample::create);

main.cpp

#include "Example.hpp"

int main()
{
    Base * p = Base::instantiate("DerivedExample");
    Base * q = Base::instantiate("AnotherExample");
}

, Registrar, ( ) , , .


( ++, ++ 98:)

virtual ~Base() { }   //  no "= default"

Base::registry_map::const_iterator it = Base::registry().find(name); // no "auto"
+6

All Articles