[mpl][fusion] making a heterogeneous collection of classes from a list of types.

Hello, I have the MPL book and I've used some metaprogramming before but I'm always at the edge of my understanding of the language when I do it. I have a problem right now which I suspect is trivial but I can't for the life of me figure out how to do it. I have a list of 25 resource types (class Sound, class Script, etc.) and since they are not mutable I want to share them so I have a resource cache template that looks something like: template< typename Resource > class Cache { public: typedef typename Tag<Resource>::type resource_tag; /// Retrieve a resource by id /// Throws cache_error if the resource couldn't be found in the Repository Resource& Retrieve( ResourceId id ) { // is the resource in the cache? typename ResourceMap::iterator it = m_resources.find( id ); if( it != m_resources.end() ) { return it->second; } else { return LoadResource( id ); } } /// Clears the cache and destructs all cached resources. void Clear() { m_resources.clear(); } private: Resource& LoadResource( ResourceId id ) { Stream stream( Repository::Instance().Retrieve( id, resource_tag::type::value ) ); if( !stream.fail() ) { Resource* res = new Resource(stream); m_resources.insert( id, res ); return *res; } else { throw cache_error( id, resource_tag::type::value ); } } typedef boost::ptr_map< ResourceId, Resource > ResourceMap; ResourceMap m_resources; }; I have a class which must contain a Cache for each of the 25 resource types and support calls to get a resource of a particular type given an id and be able to call Clear on all 25 caches. Something like class Manager { public: /// Returns Cache<Resource>::Retrieve( id ) template< typename Resource > const Resource& Get( ResourceId id ); /// Calls Cache::Clear for all resource types void Clear(); }; It would be pretty easy to just copy and paste it out 25 times but I would like to reduce code duplication and simplify maintenance through metaprogramming. I have a private boost::mpl::list25 named resource_list containing all the resource types. I think I need to transform that in to a boost::fusion::map of 25 Resource to Cache<Resource> pairs but I'm not sure that is what I really need to do or how to go about doing that. Thanks, Michael Marcin

Looking back into the MPL book I think I can create the required members
and implement Get by modifying the class in the last posting with:
template< typename Resource >
struct Cache
{
resource::Cache<Resource> value;
};
class Manager
{
public:
/// Returns Cache<Resource>::Retrieve( id )
template< typename Resource >
Resource& Get( ResourceId id )
{
return static_cast

Okay I think I've got a solution but I it is a bit ugly. Is there a
cleaner solution?
template< typename T >
struct wrap
{
};
template< typename ResourceCaches >
struct CacheClearer
{
ResourceCaches& m_caches;
CacheClearer( ResourceCaches& caches ) : m_caches( caches ) {}
template< typename Resource >
void operator()( wrap<Resource> )
{
static_cast
resource_types;
boost::mpl::inherit_linearly< resource_types, boost::mpl::inherit< Cache< boost::mpl::_2 >, boost::mpl::_1 >
::type m_caches; };
Thanks, Michael Marcin

on Thu Oct 11 2007, Michael Marcin
Okay I think I've got a solution but I it is a bit ugly. Is there a cleaner solution?
Looks OK to me. What do you find ugly about it? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
on Thu Oct 11 2007, Michael Marcin
wrote: Okay I think I've got a solution but I it is a bit ugly. Is there a cleaner solution?
Looks OK to me. What do you find ugly about it?
Thanks for looking. I guess the only concrete thing I can point to is having to declare my own template< typename T > struct wrap { }; since this seems like its probably pretty common I figured there might be one in mpl somewhere. Thanks, Michael Marcin

on Fri Oct 12 2007, Michael Marcin
David Abrahams wrote:
on Thu Oct 11 2007, Michael Marcin
wrote: Okay I think I've got a solution but I it is a bit ugly. Is there a cleaner solution?
Looks OK to me. What do you find ugly about it?
Thanks for looking.
I guess the only concrete thing I can point to is having to declare my own
template< typename T > struct wrap { };
since this seems like its probably pretty common I figured there might be one in mpl somewhere.
You can use mpl::identity for this. There's also boost/type.hpp -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

on Wed Oct 10 2007, Michael Marcin
As an aside it's syntactically heavy to have to qualify each placeholder with "boost::mpl::". Unfortunately if I don't do that it picks up boost::bind placeholders from an unnamed namespace and gives an impressive spew of error messages.
namespace m = boost::mpl::placeholders;
typedef is_same
participants (2)
-
David Abrahams
-
Michael Marcin