views:

58

answers:

2

Hi, I have a cache object that caches a number of different types of objects, as illustrated below:

class Cache
{
public:
    ObjectTable<ObjTypeA> m_objACache;
    ObjectTable<ObjTypeB> m_objBCache;
    ObjectTable<ObjTypeC> m_objCCache;
};

The (horrible) way I'm currently using the cache at the moment is directly accessing the cache class properties "m_objACache" and "m_objBCache" like this:

Cache c;
c.m_objACache.getObjectWithid(objectBuffer, 1);
c.m_objACache.getObjectWithid(objectBuffer, 2);
c.m_objBCache.getObjectWithid(objectBuffer, 3);

etc..

What I'd like to be able to do is something like this : -

class Cache
{
public:
    template <typename T>
    void getObjectWithId(T &objectBuffer, int id)
    {
        ObjectTable<T>.getObjectWithId(objectBuffer, id);
    }
};

But obviously that does not work because where I have "ObjectTable<T>" I need a variable name, but I cannot template class variables - so is there a way I can do this? Or is it going to be a case if declaring all of the variables and accessing it like this:

class Cache
{
public:
    void getObjectWithId(ObjTypeA &objectBuffer, int id)
    {
        m_objACache.getObjectWithId(objectBuffer, id);
    }

    void getObjectWithId(ObjTypeB &objectBuffer, int id)
    {
        m_objBCache.getObjectWithId(objectBuffer, id);
    }

    void getObjectWithId(ObjTypeC &objectBuffer, int id)
    {
        m_objCCache.getObjectWithId(objectBuffer, id);
    }

protected:
    ObjectTable<ObjTypeA> m_objACache;
    ObjectTable<ObjTypeB> m_objBCache;
    ObjectTable<ObjTypeC> m_objCCache;
};

Which seems very verbose..

Each object type that an ObjectTable can be used for has a common base class, so there could be some other way of doing this that may inevitably involve downcasting, but I'm hoping I can find a better way.

Thanks!

+3  A: 

Like this perhaps?

class Cache
{
 // An "envelope" type which up-casts to the right ObjectTable<T> 
 // if we have a type parameter T. 
 struct ObjectTables : ObjectTable<ObjTypeA>,  
                       ObjectTable<ObjTypeB>, 
                       ObjectTable<ObjTypeC> {};

 ObjectTables tables; 
public:

    template <typename T>
    void getObjectWithId(T &objectBuffer, int id)
    { 
        // C++ does the work here
        ObjectTable<T> &o=tables;
        t.getObjectWithId(objectBuffer, id);
    }
};

Also, it's easy to extend. Just throw in more ObjectTables<> if you need to support more types.

Luther Blissett
One could even add explicit specialisations of getObjectWithId<>() for the few exceptions where the generic version isn't good enough.
Sjoerd
@Luther Blissett: Thanks, I like it :-)
Mark
A: 

Boost.Fusion has a boost::fusion::map for this very purpose.

You map a type to another type, the first is a pure compilation hint, the second is actually instantiated.

You then request:

boost::fusion::map< std::pair<Key1,Value1> > map;
Value1& v = boost::fusion::at<Key1>(map);
Matthieu M.