Self-Registering Objects in C++
by Jim Beveridge 


Listing One
(a)
enum file_types { TYPE_UNKNOWN, TYPE_JPEG, TYPE_TIFF, TYPE_GIF };
int find_extension_type(char *ext)
{
    if (strcmp(ext, ".JPG") == 0)
        return TYPE_JPEG;
    if (strcmp(ext, ".TIF") == 0)
        return TYPE_TIFF;
    if (strcmp(ext, ".GIF") == 0)
        return TYPE_GIF;
    return TYPE_UNKNOWN;
}

(b)
int type = find_extension_type(extension);
switch(type)
{
case TYPE_JPEG:
    import_jpeg(filename);
    break;
case TYPE_TIFF:
    import_tiff(filename);
    break;
case TYPE_GIF:
    import_gif(filename);
    break;
}


Listing Two
(a)
ConversionObject* CreateConversionObject(char *ext)
{
    if (strcmp(ext, ".JPG") == 0)
        return new JpegFileConverter;
    if (strcmp(ext, ".TIF") == 0)
        return new TifFileConverter;
    if (strcmp(ext, ".GIF") == 0)
        return new GifFileConverter;
    return NULL;
}

(b)
ConversionObject* pConverter =
        CreateConversionObject(extension);
if (pConverter)
    pConverter->Import(filename);
delete pConverter;


Listing Three
class FileConverterProxyBase
{
public:
    FileConverterProxyBase();
    virtual FileConverter* CreateObject() const = 0;
    // Expose criteria here
    virtual char* GetExtension() const = 0;
    virtual bool IsCompressed() const = 0;
};
FileConverterProxyBase::FileConverterProxyBase()
{
     gConverterStore.Register(this);
}


Listing Four
template <class T>
class FileConverterProxy : public FileConverterProxyBase
{
    FileConverter* CreateObject() const
        { return new T; }
    // Member functions in T are static
    virtual char* GetExtension() const
        { return T::GetExtension(); }
    virtual bool IsCompressed() const
        { return T::IsCompressed(); }
};


Listing Five
class TiffFileConverter : public FileConverter
{
public:
    virtual void Import(const char *filename);
    virtual void Export(const char *filename);
    // These are the criteria support functions
    static char* GetExtension()
        { return ".tif"; }
    static bool IsCompressed()
        { return TRUE; }
};
FileConverterProxy<TiffFileConverter> gTiffProxy;


Listing Six
// Definition
FileConverter* FileConverterStore::CreateByExtension(
                   const char* ext)
{
    for (unsigned i=0; i< m_pConverters->size(); i++)
    if (stricmp( m_pConverters->at(i)->GetExtension(),
                ext ) == 0)
        return m_pConverters->at(i)->CreateObject();
    return NULL;
 }

// Usage
void SomeFunc()
{
    FileConverter* pConverter;
    pConverter = gConverterStore.CreateByExtension(".TIF");
    if (pConverter)
        pConverter->Import("Image.TIF");
    delete pConverter;
}






