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 {};