2001-02-12 11:17:54 +08:00
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
|
|
|
|
|
|
|
|
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
|
|
|
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
|
|
|
|
<meta name="ProgId" content="FrontPage.Editor.Document">
|
|
|
|
|
|
|
|
|
|
<title>Generic Programming Techniques</title>
|
|
|
|
|
|
|
|
|
|
<img src="../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
|
|
|
|
width="277" height="86">
|
|
|
|
|
|
|
|
|
|
<h1>Generic Programming Techniques</h1>
|
|
|
|
|
|
|
|
|
|
<p>This is an incomplete survey of some of the generic programming
|
|
|
|
|
techniques used in the <a href="../index.htm">boost</a> libraries.
|
|
|
|
|
|
|
|
|
|
<h2>Table of Contents</h2>
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
<li><a href="#traits">Traits</a>
|
|
|
|
|
|
|
|
|
|
<li><a href="#type_generator">Type Generators</a>
|
|
|
|
|
|
2001-02-12 12:03:20 +08:00
|
|
|
|
<li><a href="#object_generator">Object Generators</a>
|
2001-02-12 11:17:54 +08:00
|
|
|
|
|
|
|
|
|
<li><a href="#policies">Policies Classes</a>
|
2001-02-12 12:03:20 +08:00
|
|
|
|
|
|
|
|
|
<li><a href="#adaptors">Adaptors</a>
|
2001-02-12 11:17:54 +08:00
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<h2><a name="traits">Traits</a></h2>
|
|
|
|
|
|
|
|
|
|
<p>A traits class provides a way of associating information with another
|
|
|
|
|
type. For example, the class template <tt><a href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/iterator_traits.html">std::iterator_traits<T></a></tt>
|
|
|
|
|
looks something like this:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<pre>
|
|
|
|
|
template <class Iterator>
|
|
|
|
|
struct iterator_traits {
|
|
|
|
|
typedef ... iterator_category;
|
|
|
|
|
typedef ... value_type;
|
|
|
|
|
typedef ... difference_type;
|
|
|
|
|
typedef ... pointer;
|
|
|
|
|
typedef ... reference;
|
|
|
|
|
};
|
|
|
|
|
</pre>
|
|
|
|
|
</blockquote>
|
|
|
|
|
The traits' <tt>value_type</tt> gives generic code the type which the
|
|
|
|
|
iterator is "pointing at", while the <tt>iterator_category</tt> can be used
|
|
|
|
|
to select more efficient algorithms depending on the iterator's
|
|
|
|
|
capabilities.
|
|
|
|
|
|
|
|
|
|
<p>A key feature of traits templates is that they're <i>non-intrusive</i>:
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
<p>For an in-depth description of <tt>std::type_traits</tt>, see <a href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/iterator_traits.html">this page</a> provided
|
|
|
|
|
by SGI. Another very different expression of the traits idiom in the
|
|
|
|
|
standard is <tt>std::numeric_limits<T></tt> which provides constants
|
|
|
|
|
describing the range and capabilities of numeric types.
|
|
|
|
|
|
|
|
|
|
<h2><a name="type_generator">Type Generators</a></h2>
|
|
|
|
|
|
|
|
|
|
<p>A <i>type generator</i> 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 <tt>type</tt>. A type generator is usually used to
|
|
|
|
|
consolidate a complicated type expression into a simple one, as in
|
|
|
|
|
<tt>boost::<a href=
|
|
|
|
|
"../libs/utility/filter_iterator.hpp">filter_iterator_generator</a></tt>,
|
|
|
|
|
which looks something like this:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<pre>
|
|
|
|
|
template <class Predicate, class Iterator,
|
|
|
|
|
class Value = <i>complicated default</i>,
|
|
|
|
|
class Reference = <i>complicated default</i>,
|
|
|
|
|
class Pointer = <i>complicated default</i>,
|
|
|
|
|
class Category = <i>complicated default</i>,
|
|
|
|
|
class Distance = <i>complicated default</i>
|
|
|
|
|
>
|
|
|
|
|
struct filter_iterator_generator {
|
|
|
|
|
typedef iterator_adaptor<
|
|
|
|
|
Iterator,filter_iterator_policies<Predicate,Iterator>,
|
|
|
|
|
Value,Reference,Pointer,Category,Distance> <b>type</b>;
|
|
|
|
|
};
|
|
|
|
|
</pre>
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
|
|
<p>Now, that's complicated, but producing an adapted filter iterator is
|
|
|
|
|
much easier. You can usually just write:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<pre>
|
|
|
|
|
boost::filter_iterator_generator<my_predicate,my_base_iterator>::type
|
|
|
|
|
</pre>
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
|
|
<h2><a name="object_generator">Object Generators</a></h2>
|
|
|
|
|
|
|
|
|
|
<p>An <i>object generator</i> 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 "<tt>make_</tt>", after <tt>std::<a href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/pair.html">make_pair</a>(const<73>T&,<2C>const<73>U&)</tt>.
|
|
|
|
|
|
|
|
|
|
<p>Here is an example, using another standard object generator, <tt>std::<a
|
|
|
|
|
href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/back_insert_iterator.html">back_inserter</a>()</tt>:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<pre>
|
|
|
|
|
// 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, <b>std::back_inserter</b>(c));
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
|
|
<p>Without using the object generator the example above would look like:
|
|
|
|
|
write:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<pre>
|
|
|
|
|
// 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, <b>std::back_insert_iterator<Container></b>(c));
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
|
|
<p>As expressions get more complicated the need to reduce the verbosity of
|
|
|
|
|
type specification gets more compelling.
|
|
|
|
|
|
|
|
|
|
<h2><a name="policies">Policies Classes</a></h2>
|
|
|
|
|
|
|
|
|
|
<p>Policies classes are a simple idea we first saw described by <a href=
|
|
|
|
|
"mailto:andrewalex@hotmail.com">Andrei Alexandrescu</a>, but which we
|
|
|
|
|
snapped up and quickly applied in the <a href=
|
|
|
|
|
"../libs/utility/iterator_adaptors.htm">Iterator Adaptors</a> library. A
|
|
|
|
|
policies class is a template parameter used to transmit behaviors. A
|
|
|
|
|
detailed description by Andrei is available in <a href=
|
|
|
|
|
"http://www.cs.ualberta.ca/~hoover/cmput401/XP-Notes/xp-conf/Papers/7_3_Alexandrescu.pdf">
|
|
|
|
|
this paper</a>. He writes:
|
|
|
|
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
<p>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.
|
|
|
|
|
|
|
|
|
|
<p>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.
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
2001-02-12 12:03:20 +08:00
|
|
|
|
<p>Andrei's description of policies describe their power as being derived
|
2001-02-12 11:17:54 +08:00
|
|
|
|
from their granularity and orthogonality. Boost has probably diluted the
|
|
|
|
|
distinction in the <a href="../libs/utility/iterator_adaptors.htm">Iterator
|
|
|
|
|
Adaptors</a> library, where we transmit all of an adapted iterator's
|
|
|
|
|
behavior in a single policies class.
|
|
|
|
|
|
2001-02-12 12:03:20 +08:00
|
|
|
|
<h2><a name="adaptors">Adaptors</a></h2>
|
|
|
|
|
|
|
|
|
|
<p>An <i>adaptor</i> is a class template which builds on another type or
|
|
|
|
|
types to provide a new interface or behavioral variant. Examples of
|
|
|
|
|
standard adaptors are <a href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/ReverseIterator.html">std::reverse_iterator</a>,
|
|
|
|
|
which adapts an iterator type by reversing its motion upon
|
|
|
|
|
increment/decrement, and <a href=
|
|
|
|
|
"http://www.sgi.com/tech/stl/stack.html">std::stack</a>, which adapts a
|
|
|
|
|
container to provide a simple stack interface.
|
|
|
|
|
|
|
|
|
|
<p>A more comprehensive review of the adaptors in the standard can be found
|
|
|
|
|
<a href=
|
|
|
|
|
"http://www.cs.rpi.edu/~wiseb/xrds/ovp2-3b.html#SECTION00015000000000000000">
|
|
|
|
|
here</a>.
|
|
|
|
|
<hr>
|
|
|
|
|
|
|
|
|
|
<p>Revised
|
|
|
|
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->11
|
|
|
|
|
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<p>© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
|
|
|
|
sell and distribute this document is granted provided this copyright notice
|
|
|
|
|
appears in all copies. This document is provided "as is" without express or
|
|
|
|
|
implied warranty, and with no claim as to its suitability for any purpose.
|
|
|
|
|
|