#pragma once

#define REGISTRABLE( c )          \
public:                           \
    static const c *INSTANCE;     \
    static const int ID;          \
                                  \
private:

#define REGISTER(c, typ)


template<typename T>
class StaticRegistry
{
public:
    static StaticRegistry<T> INSTANCE;

private:
    T **registry;
    int count;

    StaticRegistry()
    {
        count = 100;
        registry = new T * [ count ];
        memset( registry, 0, sizeof( T * ) * count );
    }

    ~StaticRegistry()
    {
        for( int index = 0; index < count; index++ )
        {
            if( registry[ index ] )
            {
                registry[ index ]->release();
                registry[ index ] = 0;
            }
        }
        delete[]registry;
    }

    void registerT( T *type, int id )
    {
        if( id >= count )
        {
            T **temp = new T * [ id + 1 ];
            memcpy( temp, registry, sizeof( T * ) * count );
            memset( temp + count, 0, sizeof( T * ) * ( id + 1 - count ) );
            delete[]registry;
            registry = temp;
            count = id + 1;
        }
        registry[ id ] = type;
    }

public:
    T *zElement( int id )
    {
        if( id < 0 || id >= count )
            return 0;
        return registry[ id ];
    }

    int getCount() const
    {
        return count;
    }

    friend T;
};

template <typename T>
StaticRegistry<T> StaticRegistry<T>::INSTANCE;