Creating dynamic type in C++

You are looking for a factory

http://www.oodesign.com/factory-pattern.html

A factory is a software module (a method, a class) whose sole purpose is to create the right object for the job. An example using a factory class:

class VariantFactory
{
    MyBase* CreateObject(uint_8 value);
}

And the CreateObject method can be filled out to give you the type of object that you need.

In the case of a very small selection of objects with simple construction, a simple switch statement might suffice. As soon as you get a lot of objects or ones that require more detailed construction, a factory is quite useful.


As stated, you make a factory, but not necessarily with naive switch statements. What you can do is make a template class to create the relevant object and dynamically add these to your factory.

class VariantinatorBase {
  public:
    VariantinatorBase() {}
    virtual ~VariantinatorBase() {}
    virtual std::unique_ptr<Variant> Create() = 0;
};

template< class T >
class Variantinator : public VariantinatorBase {
  public:
    Variantinator() {}
    virtual ~Variantinator() {}
    virtual std::unique_ptr<Variant> Create() { return std::make_unique<T>(); }
};

Now you have a class factory that allows you to register these.

class VariantFactory
{
  public:
    VariantFactory()
    {
         // If you want, you can do all your Register() calls in here, and even
         // make the Register() function private.
    }

    template< uint8_t type, typename T >
    void Register()
    {
        Register( type, std::make_unique<Variantinator<T>>() );
    }

    std::unique_ptr<Variant> Create( uint8_t type )
    {
        TSwitchToVariant::iterator it = m_switchToVariant.find( type );
        if( it == m_switchToVariant.end() ) return nullptr;
        return it->second->Create();
    }

  private:
    void Register( uint8_t type, std::unique_ptr<VariantinatorBase>&& creator )
    {
        m_switchToVariant[type] = std::move(creator);
    }

    typedef std::map<uint8_t, std::unique_ptr<VariantinatorBase> > TSwitchToVariant;
    TSwitchToVariant m_switchToVariant;
};

At the beginning of your program, create the factory and register your types:

VariantFactory factory;
factory.Register<0, VariantA>();
factory.Register<1, VariantB>();
factory.Register<2, VariantC>();

Then later, you want to call on it:

std::unique_ptr<Variant> thing = factory.Create( switchValue );