views:

166

answers:

4

I'm trying to understand how variants are implemented, and reading:

http://www.codeproject.com/KB/cpp/TTLTyplist.aspx

And I'm getting the impression that I can't write a variant that takes X types; but that the template writer picks some N, and I can only have less than-N types in a variant.

Is this correct?

Thanks!

+1  A: 

That is correct under the current standard; templates can only have a fixed number of arguments, and libraries use techniques like preprocessor meta-programming to simulate variadic template parameters up to a certain set maximum. Normally this isn't much of a problem in practice because the maximums are set such to be well above what most people use.

In the new 0x standard, there is support for true variadic template parameters.

Todd Gardner
+2  A: 

Yes -- there's some limit set by the implementation of the library. IIRC, in Loki the maximum is 99 by default. Glancing at that article he's set the limit at 5, which is probably enough for a lot of work, but I can see the possibility of exceeding it; I can't quite imagine exceeding the 99 Loki allows (though in either case it's a trivial editing job to extend the limit if you want).

Jerry Coffin
+3  A: 

In C++03, there are no variadic templates. This means yes; you simply have to pick some N to go up to, and live with that.

In C++0x, there will be variadic templates, so you could use one definition for all X.

If you're looking to make changing the number easy, you can use Boost.Preprocessor and have it do the work for you:

#define MAXIMUM_TYPELIST_SIZE 20 // or something

struct empty{};

template <BOOST_PP_ENUM_BINARY_PARAMS(MAXIMUM_TYPELIST_SIZE, typename T, =empty)>
struct typelist;

template <BOOST_PP_ENUM_PARAMS(MAXIMUM_TYPELIST_SIZE, typename T)>
struct typelist
{
    typedef T1 head;
    typedef typelist<
            BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(MAXIMUM_TYPELIST_SIZE), T)> tail;
  enum
  {
    length = tail::length+1
  };
};

If MAXIMUM_TYPELIST_SIZE were 5, those macro's would expand to what the article has.

(Of course, if you're using Boost just use their meta-programming library.)

GMan
Thats actually the first acceptably readable use of Boost.PP i've seen outside their tutorials.
Georg Fritzsche
@gf: Haha. :P This ("variadic" templates) and the counter you pointed out to me on another question are the only two real uses I've gotten out of it thus far.
GMan
+2  A: 

Without variadic template support, template authors can only provide workarounds that look like variadic templates:

template<class Arg1=nil, class Arg2=nil /* , ... */>
struct foo {};

Here the number of template arguments the author provides is the limit.

If they wouldn't provide such work-arounds, you'd be forced to resort to explicit typelists, which are quite clumsy in comparison:

typedef list<T1, list<T2, list<T3, nil> > > myTypeList;
foo<myTypeList>::bar;

These are not limited to a fixed number of types, but not something i'd like to use explicitly.

With the next C++ standard this will be solved with true variadic templates:

template<class... Args> // can take 0..n arguments 
struct foo {};
Georg Fritzsche