13.13 List Parameters

Ru-Brd

A need that shows up sometimes is the ability to pass a list of types as a single template argument. Usually, this list is meant for one of two purposes: declaring a function with a parameterized number of parameters or defining a type structure with a parameterized list of members .

For example, we may want to define a template that computes the maximum of an arbitrary list of values. A potential declaration syntax uses the ellipsis token to denote that the last template parameter is meant to match an arbitrary number of arguments:

 #include <iostream>  template <typename T, ... list>  T const& max (T const&, T const&, list const&);  int main()  {      std::cout << max(1, 2, 3, 4) << std::endl;  } 

Various possibilities can be thought of to implement such a template. Here is one that doesn't require new keywords but adds a rule to function template overloading to prefer a function template without a list parameter:

 template <typename T> inline  T const& max (T const& a, T const& b)  {  // our usual binary maximum:  return a<b?b:a;  }  template <typename T, ... list> inline  T const& max (T const& a, T const& b, list const& x)  {     return max (a, max(b,x));  } 

Let's go through the steps that would make this work for the call max(1, 2, 3, 4) . Because there are four arguments, the binary max() function doesn't match, but the second one does match with T = int and list = int, int . This causes us to call the binary function template max() with the first argument equal to 1 and the second argument equal to the evaluation of max(2, 3, 4) . Again, the binary operation doesn't match, and we call the list parameter version with T = int and list = int . This time the subexpression max(b,x) expands to max(3,4) , and the recursion ends by selecting the binary template.

This works fairly well thanks to the ability of overloading function templates. There is more to it than our discussion, of course. For example, we'd have to specify precisely what list const& means in this context.

Sometimes, it may be desirable to refer to particular elements or subsets of the list. For example, we could use the subscript brackets for this purpose. The following example shows how we could construct a metaprogram to count the elements in a list using this technique:

 template <typename T>  class ListProps {    public:      enum { length = 1 };  };  template <... list>  class ListProps {    public:      enum { length = 1+ListProps<list[1 ...]>::length };  }; 

This demonstrates that list parameters may also be useful for class templates and could be combined with the class overloading concept discussed earlier to enhance various template metaprogramming techniques.

Alternatively, the list parameter could be used to declare a list of fields:

 template <... list>  class Collection {      list;  }; 

A surprising number of fundamental utilities can be built on top of such a facility. For more ideas, we suggest reading Modern C++ Design (see [AlexandrescuDesign]), where the lack of this feature is replaced by extensive template- and macro-based metaprogramming.

Ru-Brd


C++ Templates
C++ Templates: The Complete Guide
ISBN: 0201734842
EAN: 2147483647
Year: 2002
Pages: 185

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net