views:

59

answers:

2

Here's what I want to be able to type:

class foo : public watchKeys<A, B, C> {}; //Or any list of keys

Boost::mpl has sequences, which allow you to do this, but I don't want to have to do:

class foo : public watchKeys<mpl::list<A, B, C> > {};

I don't mind it being "ugly" or verbose on the inside, but I want the way watchKeys is ultimately used to be very simple and intuitive. I also can't figure out how boost is doing it, but that seems to be because there's a layer of macros between me and templates.

How might I go about this? I'd prefer not to do the giant list of templates for each number of types, but if that's the only it's the only way...

Edit: I've become fairly certain that there's no way to do what I want to do (almost, but you can't have a variable number of macro arguments), but the question is still generating useful and informative answers.

+1  A: 

The giant list of templates for each number of types is the only way to do it in the current version of C++. See boost::tuple for an example of how to go about.

C++0X supports variadic templates, but that isn't well supported yet (I think modern version of GCC have experimental support though).

Leon Timmermans
*Boost.Preprocessor* is used for such things heavily in Boost, its a matter of taste though. See e.g. `BOOST_PP_REPEAT` there: http://www.boost.org/doc/libs/1_42_0/libs/preprocessor/doc/index.html
Georg Fritzsche
In my version of boost (1.38, a year old) Boost.Preprocessor isn't used for that in boost::tuple
Leon Timmermans
I haven't looked at `tuple` explicitly, but if you ever step through e.g. `Boost.Function` you should see that.
Georg Fritzsche
Both http://stackoverflow.com/questions/2338049/inheriting-off-of-a-list-of-templated-classes-when-supplied-with-the-list-of-tem and http://stackoverflow.com/questions/1671297/how-do-i-invoke-a-non-default-constructor-for-each-inherited-type-from-a-type-lis/1671549 have more on this, but use template metaprogramming tricks to do it.
Narfanator
A: 

Alternatively you can do it recursively

template<typename Head, typename Tail>
struct list { };

struct emptylist { };

class foo : public watchKeys<list<A, 
                             list<B, 
                             list<C, emptylist> > > > { };

You can then process it like this

template<typename List>
struct process;

template<typename Head, typename Tail>
struct process< list<Head, Tail> > : process<Tail> { 
  // process Head
};

template<>
struct process<emptylist> { };
Johannes Schaub - litb
While spiffy (and a handy example for template metaprogramming) part of the desired solution is an elegant usage case, which this doesn't match.
Narfanator
@Narfanator, i'm sorry i don't understand your comment. Do you mean the syntax of `list<A, list<B, emptylist> >` is not the desired solution?
Johannes Schaub - litb
Yes, exactly. It makes a lot more intuitive sense to do it your way, but it's more verbose without adding clarity.
Narfanator