[29] | 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> |
---|
| 2 | |
---|
| 3 | <html> |
---|
| 4 | <head> |
---|
| 5 | <meta name="generator" content= |
---|
| 6 | "HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org"> |
---|
| 7 | <meta http-equiv="Content-Type" content= |
---|
| 8 | "text/html; charset=windows-1252"> |
---|
| 9 | <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> |
---|
| 10 | <meta name="ProgId" content="FrontPage.Editor.Document"> |
---|
| 11 | |
---|
| 12 | <title>Generic Programming Techniques</title> |
---|
| 13 | </head> |
---|
| 14 | |
---|
| 15 | <body bgcolor="#FFFFFF" text="#000000"> |
---|
| 16 | <img src="../boost.png" alt="boost.png (6897 bytes)" align="center" |
---|
| 17 | width="277" height="86"> |
---|
| 18 | |
---|
| 19 | <h1>Generic Programming Techniques</h1> |
---|
| 20 | |
---|
| 21 | <p>This is an incomplete survey of some of the generic programming |
---|
| 22 | techniques used in the <a href="../index.htm">boost</a> libraries.</p> |
---|
| 23 | |
---|
| 24 | <h2>Table of Contents</h2> |
---|
| 25 | |
---|
| 26 | <ul> |
---|
| 27 | <li><a href="#introduction">Introduction</a></li> |
---|
| 28 | |
---|
| 29 | <li><a href="#concept">The Anatomy of a Concept</a></li> |
---|
| 30 | |
---|
| 31 | <li><a href="#traits">Traits</a></li> |
---|
| 32 | |
---|
| 33 | <li><a href="#tag_dispatching">Tag Dispatching</a></li> |
---|
| 34 | |
---|
| 35 | <li><a href="#adaptors">Adaptors</a></li> |
---|
| 36 | |
---|
| 37 | <li><a href="#type_generator">Type Generators</a></li> |
---|
| 38 | |
---|
| 39 | <li><a href="#object_generator">Object Generators</a></li> |
---|
| 40 | |
---|
| 41 | <li><a href="#policy">Policy Classes</a></li> |
---|
| 42 | </ul> |
---|
| 43 | |
---|
| 44 | <h2><a name="introduction">Introduction</a></h2> |
---|
| 45 | |
---|
| 46 | <p>Generic programming is about generalizing software components so that |
---|
| 47 | they can be easily reused in a wide variety of situations. In C++, class |
---|
| 48 | and function templates are particularly effective mechanisms for generic |
---|
| 49 | programming because they make the generalization possible without |
---|
| 50 | sacrificing efficiency.</p> |
---|
| 51 | |
---|
| 52 | <p>As a simple example of generic programming, we will look at how one |
---|
| 53 | might generalize the <tt>memcpy()</tt> function of the C standard |
---|
| 54 | library. An implementation of <tt>memcpy()</tt> might look like the |
---|
| 55 | following:<br> |
---|
| 56 | <br> |
---|
| 57 | </p> |
---|
| 58 | |
---|
| 59 | <blockquote> |
---|
| 60 | <pre> |
---|
| 61 | void* memcpy(void* region1, const void* region2, size_t n) |
---|
| 62 | { |
---|
| 63 | const char* first = (const char*)region2; |
---|
| 64 | const char* last = ((const char*)region2) + n; |
---|
| 65 | char* result = (char*)region1; |
---|
| 66 | while (first != last) |
---|
| 67 | *result++ = *first++; |
---|
| 68 | return result; |
---|
| 69 | } |
---|
| 70 | </pre> |
---|
| 71 | </blockquote> |
---|
| 72 | The <tt>memcpy()</tt> function is already generalized to some extent by |
---|
| 73 | the use of <tt>void*</tt> so that the function can be used to copy arrays |
---|
| 74 | of different kinds of data. But what if the data we would like to copy is |
---|
| 75 | not in an array? Perhaps it is in a linked list. Can we generalize the |
---|
| 76 | notion of copy to any sequence of elements? Looking at the body of |
---|
| 77 | <tt>memcpy()</tt>, the function's <b><i>minimal requirements</i></b> are |
---|
| 78 | that it needs to <i>traverse</i> through the sequence using some sort |
---|
| 79 | of pointer, <i>access</i> elements pointed to, <i>write</i> the elements |
---|
| 80 | to the destination, and <i>compare</i> pointers to know when to stop. The |
---|
| 81 | C++ standard library groups requirements such as these into |
---|
| 82 | <b><i>concepts</i></b>, in this case the <a href= |
---|
| 83 | "http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> |
---|
| 84 | concept (for <tt>region2</tt>) and the <a href= |
---|
| 85 | "http://www.sgi.com/tech/stl/OutputIterator.html">Output Iterator</a> |
---|
| 86 | concept (for <tt>region1</tt>). |
---|
| 87 | |
---|
| 88 | <p>If we rewrite the <tt>memcpy()</tt> as a function template, and use |
---|
| 89 | the <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input |
---|
| 90 | Iterator</a> and <a href= |
---|
| 91 | "http://www.sgi.com/tech/stl/OutputIterator.html">Output Iterator</a> |
---|
| 92 | concepts to describe the requirements on the template parameters, we can |
---|
| 93 | implement a highly reusable <tt>copy()</tt> function in the following |
---|
| 94 | way:<br> |
---|
| 95 | <br> |
---|
| 96 | </p> |
---|
| 97 | |
---|
| 98 | <blockquote> |
---|
| 99 | <pre> |
---|
| 100 | template <typename InputIterator, typename OutputIterator> |
---|
| 101 | OutputIterator |
---|
| 102 | copy(InputIterator first, InputIterator last, OutputIterator result) |
---|
| 103 | { |
---|
| 104 | while (first != last) |
---|
| 105 | *result++ = *first++; |
---|
| 106 | return result; |
---|
| 107 | } |
---|
| 108 | </pre> |
---|
| 109 | </blockquote> |
---|
| 110 | |
---|
| 111 | <p>Using the generic <tt>copy()</tt> function, we can now copy elements |
---|
| 112 | from any kind of sequence, including a linked list that exports iterators |
---|
| 113 | such as <tt>std::<a href= |
---|
| 114 | "http://www.sgi.com/tech/stl/List.html">list</a></tt>.<br> |
---|
| 115 | <br> |
---|
| 116 | </p> |
---|
| 117 | |
---|
| 118 | <blockquote> |
---|
| 119 | <pre> |
---|
| 120 | #include <list> |
---|
| 121 | #include <vector> |
---|
| 122 | #include <iostream> |
---|
| 123 | |
---|
| 124 | int main() |
---|
| 125 | { |
---|
| 126 | const int N = 3; |
---|
| 127 | std::vector<int> region1(N); |
---|
| 128 | std::list<int> region2; |
---|
| 129 | |
---|
| 130 | region2.push_back(1); |
---|
| 131 | region2.push_back(0); |
---|
| 132 | region2.push_back(3); |
---|
| 133 | |
---|
| 134 | std::copy(region2.begin(), region2.end(), region1.begin()); |
---|
| 135 | |
---|
| 136 | for (int i = 0; i < N; ++i) |
---|
| 137 | std::cout << region1[i] << " "; |
---|
| 138 | std::cout << std::endl; |
---|
| 139 | } |
---|
| 140 | </pre> |
---|
| 141 | </blockquote> |
---|
| 142 | |
---|
| 143 | <h2><a name="concept">Anatomy of a Concept</a></h2> |
---|
| 144 | A <b><i>concept</i></b> is a set of requirements |
---|
| 145 | consisting of valid expressions, associated types, invariants, and |
---|
| 146 | complexity guarantees. A type that satisfies the requirements is |
---|
| 147 | said to <b><i>model</i></b> the concept. A concept can extend the |
---|
| 148 | requirements of another concept, which is called |
---|
| 149 | <b><i>refinement</i></b>. |
---|
| 150 | |
---|
| 151 | <ul> |
---|
| 152 | <li><a name="valid_expression"><b>Valid Expressions</b></a> are C++ |
---|
| 153 | expressions which must compile successfully for the objects involved in |
---|
| 154 | the expression to be considered <i>models</i> of the concept.</li> |
---|
| 155 | |
---|
| 156 | <li><a name="associated_type"><b>Associated Types</b></a> are types |
---|
| 157 | that are related to the modeling type in that they participate in one |
---|
| 158 | or more of the valid expressions. Typically associated types can be |
---|
| 159 | accessed either through typedefs nested within a class definition for |
---|
| 160 | the modeling type, or they are accessed through a <a href= |
---|
| 161 | "#traits">traits class</a>.</li> |
---|
| 162 | |
---|
| 163 | <li><b>Invariants</b> are run-time characteristics of the objects that |
---|
| 164 | must always be true, that is, the functions involving the objects must |
---|
| 165 | preserve these characteristics. The invariants often take the form of |
---|
| 166 | pre-conditions and post-conditions.</li> |
---|
| 167 | |
---|
| 168 | <li><b>Complexity Guarantees</b> are maximum limits on how long the |
---|
| 169 | execution of one of the valid expressions will take, or how much of |
---|
| 170 | various resources its computation will use.</li> |
---|
| 171 | </ul> |
---|
| 172 | |
---|
| 173 | <p>The concepts used in the C++ Standard Library are documented at the <a |
---|
| 174 | href="http://www.sgi.com/tech/stl/table_of_contents.html">SGI STL |
---|
| 175 | site</a>.</p> |
---|
| 176 | |
---|
| 177 | <h2><a name="traits">Traits</a></h2> |
---|
| 178 | |
---|
| 179 | <p>A traits class provides a way of associating information with a |
---|
| 180 | compile-time entity (a type, integral constant, or address). For example, |
---|
| 181 | the class template <tt><a href= |
---|
| 182 | "http://www.sgi.com/tech/stl/iterator_traits.html">std::iterator_traits<T></a></tt> |
---|
| 183 | looks something like this:</p> |
---|
| 184 | |
---|
| 185 | <blockquote> |
---|
| 186 | <pre> |
---|
| 187 | template <class Iterator> |
---|
| 188 | struct iterator_traits { |
---|
| 189 | typedef ... iterator_category; |
---|
| 190 | typedef ... value_type; |
---|
| 191 | typedef ... difference_type; |
---|
| 192 | typedef ... pointer; |
---|
| 193 | typedef ... reference; |
---|
| 194 | }; |
---|
| 195 | </pre> |
---|
| 196 | </blockquote> |
---|
| 197 | The traits' <tt>value_type</tt> gives generic code the type which the |
---|
| 198 | iterator is "pointing at", while the <tt>iterator_category</tt> can be |
---|
| 199 | used to select more efficient algorithms depending on the iterator's |
---|
| 200 | capabilities. |
---|
| 201 | |
---|
| 202 | <p>A key feature of traits templates is that they're |
---|
| 203 | <i>non-intrusive</i>: they allow us to associate information with |
---|
| 204 | arbitrary types, including built-in types and types defined in |
---|
| 205 | third-party libraries, Normally, traits are specified for a particular |
---|
| 206 | type by (partially) specializing the traits template.</p> |
---|
| 207 | |
---|
| 208 | <p>For an in-depth description of <tt>std::iterator_traits</tt>, see <a |
---|
| 209 | href="http://www.sgi.com/tech/stl/iterator_traits.html">this page</a> |
---|
| 210 | provided by SGI. Another very different expression of the traits idiom in |
---|
| 211 | the standard is <tt>std::numeric_limits<T></tt> which provides |
---|
| 212 | constants describing the range and capabilities of numeric types.</p> |
---|
| 213 | |
---|
| 214 | <h2><a name="tag_dispatching">Tag Dispatching</a></h2> |
---|
| 215 | |
---|
| 216 | <p>Tag dispatching is a way of using function overloading to |
---|
| 217 | dispatch based on properties of a type, and is often used hand in |
---|
| 218 | hand with traits classes. A good example of this synergy is the |
---|
| 219 | implementation of the <a href= |
---|
| 220 | "http://www.sgi.com/tech/stl/advance.html"><tt>std::advance()</tt></a> |
---|
| 221 | function in the C++ Standard Library, which increments an iterator |
---|
| 222 | <tt>n</tt> times. Depending on the kind of iterator, there are different |
---|
| 223 | optimizations that can be applied in the implementation. If the iterator |
---|
| 224 | is <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">random |
---|
| 225 | access</a> (can jump forward and backward arbitrary distances), then the |
---|
| 226 | <tt>advance()</tt> function can simply be implemented with <tt>i += |
---|
| 227 | n</tt>, and is very efficient: constant time. Other iterators must be |
---|
| 228 | <tt>advance</tt>d in steps, making the operation linear in n. If the |
---|
| 229 | iterator is <a href= |
---|
| 230 | "http://www.sgi.com/tech/stl/BidirectionalIterator.html">bidirectional</a>, |
---|
| 231 | then it makes sense for <tt>n</tt> to be negative, so we must decide |
---|
| 232 | whether to increment or decrement the iterator.</p> |
---|
| 233 | |
---|
| 234 | <p>The relation between tag dispatching and traits classes is that the |
---|
| 235 | property used for dispatching (in this case the |
---|
| 236 | <tt>iterator_category</tt>) is often accessed through a traits class. The |
---|
| 237 | main <tt>advance()</tt> function uses the <a href= |
---|
| 238 | "http://www.sgi.com/tech/stl/iterator_traits.html"><tt>iterator_traits</tt></a> |
---|
| 239 | class to get the <tt>iterator_category</tt>. It then makes a call the the |
---|
| 240 | overloaded <tt>advance_dispatch()</tt> function. The appropriate |
---|
| 241 | <tt>advance_dispatch()</tt> is selected by the compiler based on whatever |
---|
| 242 | type the <tt>iterator_category</tt> resolves to, either <a href= |
---|
| 243 | "http://www.sgi.com/tech/stl/input_iterator_tag.html"><tt>input_iterator_tag</tt></a>, |
---|
| 244 | <a href= |
---|
| 245 | "http://www.sgi.com/tech/stl/bidirectional_iterator_tag.html"><tt>bidirectional_iterator_tag</tt></a>, |
---|
| 246 | or <a href= |
---|
| 247 | "http://www.sgi.com/tech/stl/random_access_iterator_tag.html"><tt>random_access_iterator_tag</tt></a>. |
---|
| 248 | A <b><i>tag</i></b> is simply a class whose only purpose is to convey |
---|
| 249 | some property for use in tag dispatching and similar techniques. Refer to |
---|
| 250 | <a href="http://www.sgi.com/tech/stl/iterator_tags.html">this page</a> |
---|
| 251 | for a more detailed description of iterator tags.</p> |
---|
| 252 | |
---|
| 253 | <blockquote> |
---|
| 254 | <pre> |
---|
| 255 | namespace std { |
---|
| 256 | struct input_iterator_tag { }; |
---|
| 257 | struct bidirectional_iterator_tag { }; |
---|
| 258 | struct random_access_iterator_tag { }; |
---|
| 259 | |
---|
| 260 | namespace detail { |
---|
| 261 | template <class InputIterator, class Distance> |
---|
| 262 | void advance_dispatch(InputIterator& i, Distance n, <b>input_iterator_tag</b>) { |
---|
| 263 | while (n--) ++i; |
---|
| 264 | } |
---|
| 265 | |
---|
| 266 | template <class BidirectionalIterator, class Distance> |
---|
| 267 | void advance_dispatch(BidirectionalIterator& i, Distance n, |
---|
| 268 | <b>bidirectional_iterator_tag</b>) { |
---|
| 269 | if (n >= 0) |
---|
| 270 | while (n--) ++i; |
---|
| 271 | else |
---|
| 272 | while (n++) --i; |
---|
| 273 | } |
---|
| 274 | |
---|
| 275 | template <class RandomAccessIterator, class Distance> |
---|
| 276 | void advance_dispatch(RandomAccessIterator& i, Distance n, |
---|
| 277 | <b>random_access_iterator_tag</b>) { |
---|
| 278 | i += n; |
---|
| 279 | } |
---|
| 280 | } |
---|
| 281 | |
---|
| 282 | template <class InputIterator, class Distance> |
---|
| 283 | void advance(InputIterator& i, Distance n) { |
---|
| 284 | typename <b>iterator_traits<InputIterator>::iterator_category</b> category; |
---|
| 285 | detail::advance_dispatch(i, n, <b>category</b>); |
---|
| 286 | } |
---|
| 287 | } |
---|
| 288 | </pre> |
---|
| 289 | </blockquote> |
---|
| 290 | |
---|
| 291 | <h2><a name="adaptors">Adaptors</a></h2> |
---|
| 292 | |
---|
| 293 | <p>An <i>adaptor</i> is a class template which builds on another type or |
---|
| 294 | types to provide a new interface or behavioral variant. Examples of |
---|
| 295 | standard adaptors are <a href= |
---|
| 296 | "http://www.sgi.com/tech/stl/ReverseIterator.html">std::reverse_iterator</a>, |
---|
| 297 | which adapts an iterator type by reversing its motion upon |
---|
| 298 | increment/decrement, and <a href= |
---|
| 299 | "http://www.sgi.com/tech/stl/stack.html">std::stack</a>, which adapts a |
---|
| 300 | container to provide a simple stack interface.</p> |
---|
| 301 | |
---|
| 302 | <p>A more comprehensive review of the adaptors in the standard can be |
---|
| 303 | found <a href="http://portal.acm.org/citation.cfm?id=249118.249120"> |
---|
| 304 | here</a>.</p> |
---|
| 305 | |
---|
| 306 | <h2><a name="type_generator">Type Generators</a></h2> |
---|
| 307 | |
---|
| 308 | <p><b>Note:</b> The <i>type generator</i> concept has largely been |
---|
| 309 | superseded by the more refined notion of a <a href= |
---|
| 310 | "../libs/mpl/doc/refmanual/metafunction.html"><i>metafunction</i></a>. See |
---|
| 311 | <i><a href="http://www.boost-consulting.com/mplbook">C++ Template |
---|
| 312 | Metaprogramming</a></i> for an in-depth discussion of metafunctions.</p> |
---|
| 313 | |
---|
| 314 | <p>A <i>type generator</i> is a template whose only purpose is to |
---|
| 315 | synthesize a new type or types based on its template argument(s)<a href= |
---|
| 316 | "#1">[1]</a>. The generated type is usually expressed as a nested typedef |
---|
| 317 | named, appropriately <tt>type</tt>. A type generator is usually used to |
---|
| 318 | consolidate a complicated type expression into a simple one. This example |
---|
| 319 | uses an old version of <tt><a href= |
---|
| 320 | "../libs/iterator/doc/iterator_adaptor.html">iterator_adaptor</a></tt> |
---|
| 321 | whose design didn't allow derived iterator types. As a result, every |
---|
| 322 | adapted iterator had to be a specialization of <tt>iterator_adaptor</tt> |
---|
| 323 | itself and generators were a convenient way to produce those types.</p> |
---|
| 324 | |
---|
| 325 | <blockquote> |
---|
| 326 | <pre> |
---|
| 327 | template <class Predicate, class Iterator, |
---|
| 328 | class Value = <i>complicated default</i>, |
---|
| 329 | class Reference = <i>complicated default</i>, |
---|
| 330 | class Pointer = <i>complicated default</i>, |
---|
| 331 | class Category = <i>complicated default</i>, |
---|
| 332 | class Distance = <i>complicated default</i> |
---|
| 333 | > |
---|
| 334 | struct filter_iterator_generator { |
---|
| 335 | typedef iterator_adaptor< |
---|
| 336 | |
---|
| 337 | Iterator,filter_iterator_policies<Predicate,Iterator>, |
---|
| 338 | Value,Reference,Pointer,Category,Distance> <b>type</b>; |
---|
| 339 | }; |
---|
| 340 | </pre> |
---|
| 341 | </blockquote> |
---|
| 342 | |
---|
| 343 | <p>Now, that's complicated, but producing an adapted filter iterator |
---|
| 344 | using the generator is much easier. You can usually just write:</p> |
---|
| 345 | |
---|
| 346 | <blockquote> |
---|
| 347 | <pre> |
---|
| 348 | boost::filter_iterator_generator<my_predicate,my_base_iterator>::type |
---|
| 349 | </pre> |
---|
| 350 | </blockquote> |
---|
| 351 | |
---|
| 352 | <h2><a name="object_generator">Object Generators</a></h2> |
---|
| 353 | |
---|
| 354 | <p>An <i>object generator</i> is a function template whose only purpose |
---|
| 355 | is to construct a new object out of its arguments. Think of it as a kind |
---|
| 356 | of generic constructor. An object generator may be more useful than a |
---|
| 357 | plain constructor when the exact type to be generated is difficult or |
---|
| 358 | impossible to express and the result of the generator can be passed |
---|
| 359 | directly to a function rather than stored in a variable. Most Boost |
---|
| 360 | object generators are named with the prefix "<tt>make_</tt>", after |
---|
| 361 | <tt>std::<a href= |
---|
| 362 | "http://www.sgi.com/tech/stl/pair.html">make_pair</a>(const T&, const U&)</tt>.</p> |
---|
| 363 | |
---|
| 364 | <p>For example, given:</p> |
---|
| 365 | |
---|
| 366 | <blockquote> |
---|
| 367 | <pre> |
---|
| 368 | struct widget { |
---|
| 369 | void tweak(int); |
---|
| 370 | }; |
---|
| 371 | std::vector<widget *> widget_ptrs; |
---|
| 372 | </pre> |
---|
| 373 | </blockquote> |
---|
| 374 | By chaining two standard object generators, <tt>std::<a href= |
---|
| 375 | "http://www.dinkumware.com/htm_cpl/functio2.html#bind2nd">bind2nd</a>()</tt> |
---|
| 376 | and <tt>std::<a href= |
---|
| 377 | "http://www.dinkumware.com/htm_cpl/functio2.html#mem_fun">mem_fun</a>()</tt>, |
---|
| 378 | we can easily tweak all widgets: |
---|
| 379 | |
---|
| 380 | <blockquote> |
---|
| 381 | <pre> |
---|
| 382 | void tweak_all_widgets1(int arg) |
---|
| 383 | { |
---|
| 384 | for_each(widget_ptrs.begin(), widget_ptrs.end(), |
---|
| 385 | <b>bind2nd</b>(std::<b>mem_fun</b>(&widget::tweak), arg)); |
---|
| 386 | } |
---|
| 387 | </pre> |
---|
| 388 | </blockquote> |
---|
| 389 | |
---|
| 390 | <p>Without using object generators the example above would look like |
---|
| 391 | this:</p> |
---|
| 392 | |
---|
| 393 | <blockquote> |
---|
| 394 | <pre> |
---|
| 395 | void tweak_all_widgets2(int arg) |
---|
| 396 | { |
---|
| 397 | for_each(struct_ptrs.begin(), struct_ptrs.end(), |
---|
| 398 | <b>std::binder2nd<std::mem_fun1_t<void, widget, int> ></b>( |
---|
| 399 | std::<b>mem_fun1_t<void, widget, int></b>(&widget::tweak), arg)); |
---|
| 400 | } |
---|
| 401 | </pre> |
---|
| 402 | </blockquote> |
---|
| 403 | |
---|
| 404 | <p>As expressions get more complicated the need to reduce the verbosity |
---|
| 405 | of type specification gets more compelling.</p> |
---|
| 406 | |
---|
| 407 | <h2><a name="policy">Policy Classes</a></h2> |
---|
| 408 | |
---|
| 409 | <p>A policy class is a template parameter used to transmit behavior. An |
---|
| 410 | example from the standard library is <tt>std::<a href= |
---|
| 411 | "http://www.dinkumware.com/htm_cpl/memory.html#allocator">allocator</a></tt>, |
---|
| 412 | which supplies memory management behaviors to standard <a href= |
---|
| 413 | "http://www.sgi.com/tech/stl/Container.html">containers</a>.</p> |
---|
| 414 | |
---|
| 415 | <p>Policy classes have been explored in detail by <a href= |
---|
| 416 | "http://www.moderncppdesign.com/">Andrei Alexandrescu</a> in <a href= |
---|
| 417 | "http://www.informit.com/articles/article.asp?p=167842">this chapter</a> |
---|
| 418 | of his book, <i>Modern C++ Design</i>. He writes:</p> |
---|
| 419 | |
---|
| 420 | <blockquote> |
---|
| 421 | <p>In brief, policy-based class design fosters assembling a class with |
---|
| 422 | complex behavior out of many little classes (called policies), each of |
---|
| 423 | which takes care of only one behavioral or structural aspect. As the |
---|
| 424 | name suggests, a policy establishes an interface pertaining to a |
---|
| 425 | specific issue. You can implement policies in various ways as long as |
---|
| 426 | you respect the policy interface.</p> |
---|
| 427 | |
---|
| 428 | <p>Because you can mix and match policies, you can achieve a |
---|
| 429 | combinatorial set of behaviors by using a small core of elementary |
---|
| 430 | components.</p> |
---|
| 431 | </blockquote> |
---|
| 432 | |
---|
| 433 | <p>Andrei's description of policy classes suggests that their power is |
---|
| 434 | derived from granularity and orthogonality. Less-granular policy |
---|
| 435 | interfaces have been shown to work well in practice, though. <a href= |
---|
| 436 | "http://cvs.sourceforge.net/viewcvs.py/*checkout*/boost/boost/libs/utility/Attic/iterator_adaptors.pdf"> |
---|
| 437 | This paper</a> describes an old version of <tt><a href= |
---|
| 438 | "../libs/iterator/doc/iterator_adaptor.html">iterator_adaptor</a></tt> |
---|
| 439 | that used non-orthogonal policies. There is also precedent in the |
---|
| 440 | standard library: <tt><a href= |
---|
| 441 | "http://www.dinkumware.com/htm_cpl/string2.html#char_traits">std::char_traits</a></tt>, |
---|
| 442 | despite its name, acts as a policies class that determines the behaviors |
---|
| 443 | of <a href= |
---|
| 444 | "http://www.dinkumware.com/htm_cpl/string2.html#basic_string">std::basic_string</a>.</p> |
---|
| 445 | |
---|
| 446 | <h2>Notes</h2> |
---|
| 447 | <a name="1">[1]</a> Type generators are sometimes viewed as a workaround |
---|
| 448 | for the lack of ``templated typedefs'' in C++. |
---|
| 449 | <hr> |
---|
| 450 | |
---|
| 451 | <p>Revised |
---|
| 452 | <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 |
---|
| 453 | August 2004<!--webbot bot="Timestamp" endspan i-checksum="14885" --> |
---|
| 454 | </p> |
---|
| 455 | |
---|
| 456 | <p>© Copyright David Abrahams 2001. Permission to copy, use, modify, |
---|
| 457 | sell and distribute this document is granted provided this copyright |
---|
| 458 | notice appears in all copies. This document is provided "as is" without |
---|
| 459 | express or implied warranty, and with no claim as to its suitability for |
---|
| 460 | any purpose. |
---|
| 461 | <!-- LocalWords: HTML html charset gif alt htm struct SGI namespace std libs |
---|
| 462 | --> |
---|
| 463 | |
---|
| 464 | <!-- LocalWords: InputIterator BidirectionalIterator RandomAccessIterator pdf |
---|
| 465 | --> |
---|
| 466 | |
---|
| 467 | <!-- LocalWords: typename Alexandrescu templated Andrei's Abrahams memcpy int |
---|
| 468 | --> |
---|
| 469 | <!-- LocalWords: const OutputIterator iostream pre cpl |
---|
| 470 | --> |
---|
| 471 | </p> |
---|
| 472 | </body> |
---|
| 473 | </html> |
---|
| 474 | |
---|