more/generic_programming.html

205 lines
8.1 KiB
HTML
Raw Normal View History

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>
<li><a href="#object_generator">Object Generators</a>
2001-02-12 11:17:54 +08:00
<li><a href="#policies">Policies Classes</a>
<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&lt;T&gt;</a></tt>
looks something like this:
<blockquote>
<pre>
template &lt;class Iterator&gt;
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&lt;T&gt;</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 &lt;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>
&gt;
struct filter_iterator_generator {
typedef iterator_adaptor&lt;
Iterator,filter_iterator_policies&lt;Predicate,Iterator&gt;,
Value,Reference,Pointer,Category,Distance&gt; <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&lt;my_predicate,my_base_iterator&gt;::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&amp;,<2C>const<73>U&amp;)</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 &lt;class Container, class Iterator&gt;
void append_sequence(Container&amp; 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 &lt;class Container, class Iterator&gt;
void append_sequence(Container&amp; c, Iterator start, Iterator finish)
{
std::copy(start, finish, <b>std::back_insert_iterator&lt;Container&gt;</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>
<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.
<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>&copy; 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.