1

In one of my projects, I have the following class template hierarchy :

template <typename FruitType, typename ParentFilterType = void>
class filter;

template <typename FruitType> // Specialization when no parent filter is needed
class filter<FruitType, void>;

Where FruitType can be anything. Let's say it is one of apple, banana or orange. So basically, a filter can have its own parent filter type.

I have no control over the filter code: it must remain as it is.

The user code usually looks like:

filter<apple, filter<banana, filter<orange> > > my_apple_filter;

Obviously, this is a bit verbose. I wondered if it is possible to get something more readable. Something like:

complex_filter<apple, banana, orange>::type my_apple_filter;

Where complex_filter<apple, banana, orange>::type would resolve to filter<apple, filter<banana, filter<orange> > >.

I tried with complex_filter being a struct template with a typedef inside but had no success so far. The number of template parameters should be variable (from, say, 1 to 5).

Have you ever needed something similar ? How could I do that ?

(I unfortunately cannot use C++0x but if there is a nicer solution with it, feel free to post it as it is always good to know)

Thank you.

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • can you use boost? boost::mpl has type vectors and also metafucntions that let you do such things – PlasmaHH Aug 16 '11 at 13:06
  • C++03 or C++0x? In C++0x you can probably use a variadic template to simplify the syntax – David Rodríguez - dribeas Aug 16 '11 at 14:03
  • @David Rodríguez - dribeas: I stated in the question that I have to work with C++03 but am open to solutions in C++0x out of curiosity. I will definitely take a look at variadic templates. Thank you for the suggestion. – ereOn Aug 16 '11 at 14:06
  • With variadic templates it is easy to just inherit from some template xxx : xxx, T{}; or similar. – PlasmaHH Aug 16 '11 at 15:06

2 Answers2

4

In C++0x, it would be variadic template.

Without C++0x, you can simply use a large list of parameters, with defaults supplied.

template <typename F0, typename F1 = void, typename F2 = void, typename F3 = void>
struct complex_filter
{
  typedef filter<F0, typename complex_filter<F1, F2, F3>::type> type;
};

template <>
struct complex_filter<void,void,void,void>
{
  typedef void type;
};

This can then be used as you wanted, and you will have to extend it manually if you ever want more parameters.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Thank you very much ! Exactly what I wanted. (I just had to replace `class` by `struct` but I guess it was a typo because `type` wouldn't be accessible otherwise) – ereOn Aug 16 '11 at 14:03
0

what you tried should work, sort of:

template< class A, class B >
struct complex_filter2
{
  typedef typename filter< A, filter< B > > type;
};

template< class A, class B, class C >
struct complex_filter3
{
  typedef typename filter< A, filter< B, filter< C > > > type;
};

//etc
stijn
  • 34,664
  • 13
  • 111
  • 163
  • And, yes, you have to specialise for each dimension... at least pre-C++0x! – Lightness Races in Orbit Aug 16 '11 at 13:08
  • Thank you for your answer. Is there any solution that would not require to write `N` different `complex_filter` `struct` templates ? @Tomalak Geret'kal: Just for learning purposes: what does C++0x provide that helps with this regard ? – ereOn Aug 16 '11 at 13:09
  • @ereOn: C++0x provides variadic templates, ie the ability of handling an a-priori unknown number of parameters. – Matthieu M. Aug 16 '11 at 13:18
  • @ereOn: Boost.Preprocessor is pretty handy to generate repetitive code like this. – Luc Touraille Aug 16 '11 at 13:22
  • @ereOn: c++0x would let you write a varadic template, with a variable number of arguments. So you would end up writing it recursively, but you would have one template. – Dave S Aug 16 '11 at 13:25