| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
- <html>
- <head>
- <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>
- </head>
- <body bgcolor="#FFFFFF" text="#000000">
- <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="#tag_dispatching">Tag Dispatching</a>
- <li><a href="#type_generator">Type Generators</a>
- <li><a href="#object_generator">Object Generators</a>
- <li><a href="#policies">Policies Classes</a>
- <li><a href="#adaptors">Adaptors</a>
- </ul>
- <h2><a name="traits">Traits</a></h2>
- <p>A traits class provides a way of associating information with a
- compile-time entity (a type, integral constant, or address). 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::iterator_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="tag_dispatching">Tag Dispatching</a></h2>
- <p>
- A technique that often goes hand in hand with traits classes is
- tag dispatching, which is a way of using function overloading to
- dispatch based on properties of a type. A good example of this is
- the implementation of the <a
- href="http://www.sgi.com/tech/stl/advance.html"><tt>std::advance()</tt></a>
- function in the C++ Standard Library, which increments an
- iterator <tt>n</tt> times. Depending on the kind of iterator,
- there are different optimizations that can be applied in the
- implementation. If the iterator is <a
- href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">random
- access</a> (can jump forward and backward arbitrary distances),
- then the <tt>advance()</tt> function can simply be implemented
- with <tt>i += n</tt>, and is very efficient: constant time. If
- the iterator is <a
- href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">bidirectional</a>,
- then it makes sense for <tt>n</tt> to be negative, we can
- decrement the iterator <tt>n</tt> times.
- </p>
- <p>
- The relation between tag dispatching and traits classes is
- that the property used for dispatching (in this case the
- <tt>iterator_category</tt>) is accessed through a traits class.
- The main <tt>advance()</tt> function uses the <a
- href="http://www.sgi.com/tech/stl/iterator_traits.html"><tt>iterator_traits</tt></a>
- class to get the <tt>iterator_category</tt>. It then makes a call
- the the overloaded <tt>advance_dispatch()</tt> function.
- The
- appropriate <tt>advance_dispatch()</tt> is selected by the
- compiler based on whatever type the <tt>iterator_category</tt>
- resolves to, either <a
- href="http://www.sgi.com/tech/stl/input_iterator_tag.html">
- <tt>input_iterator_tag</tt></a>, <a
- href="http://www.sgi.com/tech/stl/bidirectional_iterator_tag.html">
- <tt>bidirectional_iterator_tag</tt></a>, or <a
- href="http://www.sgi.com/tech/stl/random_access_iterator_tag.html">
- <tt>random_access_iterator_tag</tt></a>. A <b><i>tag</i></b> is
- simply a class whose only purpose is to convey some property for
- use in tag dispatching and similar techniques. Refer to <a
- href="http://www.sgi.com/tech/stl/iterator_tags.html">this
- page</a> for a more detailed description of iterator tags.
- </p>
- <blockquote>
- <pre>
- namespace std {
- struct input_iterator_tag { };
- struct bidirectional_iterator_tag { };
- struct random_access_iterator_tag { };
- namespace detail {
- template <class InputIterator, class Distance>
- void advance_dispatch(InputIterator& i, Distance n, <b>input_iterator_tag</b>) {
- while (n--) ++i;
- }
- template <class BidirectionalIterator, class Distance>
- void advance_dispatch(BidirectionalIterator& i, Distance n,
- <b>bidirectional_iterator_tag</b>) {
- if (n >= 0)
- while (n--) ++i;
- else
- while (n++) --i;
- }
- template <class RandomAccessIterator, class Distance>
- void advance_dispatch(RandomAccessIterator& i, Distance n,
- <b>random_access_iterator_tag</b>) {
- i += n;
- }
- }
- template <class InputIterator, class Distance>
- void advance(InputIterator& i, Distance n) {
- typename <b>iterator_traits<InputIterator>::iterator_category</b> category;
- detail::advance_dispatch(i, n, <b>category</b>);
- }
- }
- </pre>
- </blockquote>
- <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 T&, const 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>A policies class is a template parameter used to transmit
- behaviors. An example from the standard library is <tt>std::<a
- href="http://www.dinkumware.com/htm_cpl/memory.html#allocator"></a></tt>,
- which supplies memory management behaviors to standard <a
- href="http://www.sgi.com/tech/stl/Container.html">containers</a>.
- <p>Policies classes have been explored in detail by <a href=
- "mailto:andrewalex@hotmail.com">Andrei Alexandrescu</a> 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
- 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. There is precedent for this, however:
- <tt><a
- href="http://www.dinkumware.com/htm_cpl/string2.html#char_traits">std::char_traits</a></tt>,
- despite its name, acts as a policies class that determines the behaviors of
- <a
- href="http://www.dinkumware.com/htm_cpl/string2.html#basic_string">std::basic_string</a>.
- <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 -->12 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14377" -->
- <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.
- <!-- LocalWords: HTML html charset gif alt htm struct SGI namespace std libs
- -->
- <!-- LocalWords: InputIterator BidirectionalIterator RandomAccessIterator pdf
- -->
- <!-- LocalWords: typename Alexandrescu templated Andrei's Abrahams
- -->
- </body>
- </html>
|