This is an incomplete survey of some of the generic programming techniques used in the boost libraries.
A traits class provides a way of associating information with another type. For example, the class template std::iterator_traits<T> looks something like this:
The traits' value_type gives generic code the type which the iterator is "pointing at", while the iterator_category can be used to select more efficient algorithms depending on the iterator's capabilities.template <class Iterator> struct iterator_traits { typedef ... iterator_category; typedef ... value_type; typedef ... difference_type; typedef ... pointer; typedef ... reference; };
A key feature of traits templates is that they're non-intrusive: they allow us to associate information with arbitrary types, including built-in types and types defined in third-party libraries, Normally, traits are specified for a particular type by (partially) specializing the traits template.
For an in-depth description of std::type_traits, see this page provided by SGI. Another very different expression of the traits idiom in the standard is std::numeric_limits<T> which provides constants describing the range and capabilities of numeric types.
A type generator is a template whose only purpose is to synthesize a single new type based on its template argument(s). The generated type is usually expressed as a nested typedef named, appropriately type. A type generator is usually used to consolidate a complicated type expression into a simple one, as in boost::filter_iterator_generator, which looks something like this:
template <class Predicate, class Iterator, class Value = complicated default, class Reference = complicated default, class Pointer = complicated default, class Category = complicated default, class Distance = complicated default > struct filter_iterator_generator { typedef iterator_adaptor< Iterator,filter_iterator_policies<Predicate,Iterator>, Value,Reference,Pointer,Category,Distance> type; };
Now, that's complicated, but producing an adapted filter iterator is much easier. You can usually just write:
boost::filter_iterator_generator<my_predicate,my_base_iterator>::type
An object generator is a function template whose only purpose is to construct a new object out of its arguments. Think of it as a kind of generic constructor. An object generator may be more useful than a plain constructor when the exact type to be generated is difficult or impossible to express and the result of the generator can be passed directly to a function rather than stored in a variable. Most object generators are named with the prefix "make_", after std::make_pair(const T&, const U&).
Here is an example, using another standard object generator, std::back_inserter():
// Append the items in [start, finish) to c template <class Container, class Iterator> void append_sequence(Container& c, Iterator start, Iterator finish) { std::copy(start, finish, std::back_inserter(c)); }
Without using the object generator the example above would look like: write:
// Append the items in [start, finish) to c template <class Container, class Iterator> void append_sequence(Container& c, Iterator start, Iterator finish) { std::copy(start, finish, std::back_insert_iterator<Container>(c)); }
As expressions get more complicated the need to reduce the verbosity of type specification gets more compelling.
Policies classes are a simple idea we first saw described by Andrei Alexandrescu, but which we snapped up and quickly applied in the Iterator Adaptors library. A policies class is a template parameter used to transmit behaviors. A detailed description by Andrei is available in this paper. He writes:
Policy classes are implementations of punctual design choices. They are inherited from, or contained within, other classes. They provide different strategies under the same syntactic interface. A class using policies is templated having one template parameter for each policy it uses. This allows the user to select the policies needed.
The power of policy classes comes from their ability to combine freely. By combining several policy classes in a template class with multiple parameters, one achieves combinatorial behaviors with a linear amount of code.
Andrei's description of policies describe their power as being derived from their granularity and orthogonality. Boost has probably diluted the distinction in the Iterator Adaptors library, where we transmit all of an adapted iterator's behavior in a single policies class.