| [12] | 1 | <html> |
|---|
| 2 | <head> |
|---|
| 3 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
|---|
| 4 | <title>Design Overview</title> |
|---|
| 5 | <link rel="stylesheet" href="../boostbook.css" type="text/css"> |
|---|
| 6 | <meta name="generator" content="DocBook XSL Stylesheets V1.69.1"> |
|---|
| 7 | <link rel="start" href="../index.html" title="The Boost C++ Libraries"> |
|---|
| 8 | <link rel="up" href="../variant.html" title="Chapter 15. Boost.Variant"> |
|---|
| 9 | <link rel="prev" href="../visitor_ptr.html" title="Function template visitor_ptr"> |
|---|
| 10 | <link rel="next" href="misc.html" title="Miscellaneous Notes"> |
|---|
| 11 | </head> |
|---|
| 12 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
|---|
| 13 | <table cellpadding="2" width="100%"> |
|---|
| 14 | <td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td> |
|---|
| 15 | <td align="center"><a href="../../../index.htm">Home</a></td> |
|---|
| 16 | <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> |
|---|
| 17 | <td align="center"><a href="../../../people/people.htm">People</a></td> |
|---|
| 18 | <td align="center"><a href="../../../more/faq.htm">FAQ</a></td> |
|---|
| 19 | <td align="center"><a href="../../../more/index.htm">More</a></td> |
|---|
| 20 | </table> |
|---|
| 21 | <hr> |
|---|
| 22 | <div class="spirit-nav"> |
|---|
| 23 | <a accesskey="p" href="../visitor_ptr.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../variant.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="misc.html"><img src="../images/next.png" alt="Next"></a> |
|---|
| 24 | </div> |
|---|
| 25 | <div class="section" lang="en"> |
|---|
| 26 | <div class="titlepage"><div><div><h3 class="title"> |
|---|
| 27 | <a name="variant.design"></a>Design Overview</h3></div></div></div> |
|---|
| 28 | <div class="toc"><dl><dt><span class="section"><a href="design.html#variant.design.never-empty">"Never-Empty" Guarantee</a></span></dt></dl></div> |
|---|
| 29 | <div class="section" lang="en"> |
|---|
| 30 | <div class="titlepage"><div><div><h4 class="title"> |
|---|
| 31 | <a name="variant.design.never-empty"></a>"Never-Empty" Guarantee</h4></div></div></div> |
|---|
| 32 | <div class="toc"><dl> |
|---|
| 33 | <dt><span class="section"><a href="design.html#variant.design.never-empty.guarantee">The Guarantee</a></span></dt> |
|---|
| 34 | <dt><span class="section"><a href="design.html#variant.design.never-empty.problem">The Implementation Problem</a></span></dt> |
|---|
| 35 | <dt><span class="section"><a href="design.html#variant.design.never-empty.memcpy-solution">The "Ideal" Solution: False Hopes</a></span></dt> |
|---|
| 36 | <dt><span class="section"><a href="design.html#variant.design.never-empty.double-storage-solution">An Initial Solution: Double Storage</a></span></dt> |
|---|
| 37 | <dt><span class="section"><a href="design.html#variant.design.never-empty.heap-backup-solution">Current Approach: Temporary Heap Backup</a></span></dt> |
|---|
| 38 | <dt><span class="section"><a href="design.html#variant.design.never-empty.optimizations">Enabling Optimizations</a></span></dt> |
|---|
| 39 | <dt><span class="section"><a href="design.html#variant.design.never-empty.roadmap">Future Direction: Policy-based Implementation</a></span></dt> |
|---|
| 40 | </dl></div> |
|---|
| 41 | <div class="section" lang="en"> |
|---|
| 42 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 43 | <a name="variant.design.never-empty.guarantee"></a>The Guarantee</h5></div></div></div> |
|---|
| 44 | <p>All instances <code class="computeroutput">v</code> of type |
|---|
| 45 | <code class="computeroutput"><a href="../boost/variant.html" title="Class template variant">variant</a><T1,T2,...,TN></code> |
|---|
| 46 | guarantee that <code class="computeroutput">v</code> has constructed content of one of the |
|---|
| 47 | types <code class="computeroutput">T<span class="emphasis"><em>i</em></span></code>, even if an operation on |
|---|
| 48 | <code class="computeroutput">v</code> has previously failed.</p> |
|---|
| 49 | <p>This implies that <code class="computeroutput">variant</code> may be viewed precisely as |
|---|
| 50 | a union of <span class="emphasis"><em>exactly</em></span> its bounded types. This |
|---|
| 51 | "never-empty" property insulates the user from the |
|---|
| 52 | possibility of undefined <code class="computeroutput">variant</code> content and the |
|---|
| 53 | significant additional complexity-of-use attendant with such a |
|---|
| 54 | possibility.</p> |
|---|
| 55 | </div> |
|---|
| 56 | <div class="section" lang="en"> |
|---|
| 57 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 58 | <a name="variant.design.never-empty.problem"></a>The Implementation Problem</h5></div></div></div> |
|---|
| 59 | <p>While the |
|---|
| 60 | <a href="design.html#variant.design.never-empty.guarantee" title="The Guarantee">never-empty guarantee</a> |
|---|
| 61 | might at first seem "obvious," it is in fact not even |
|---|
| 62 | straightforward how to implement it in general (i.e., without |
|---|
| 63 | unreasonably restrictive additional requirements on |
|---|
| 64 | <a href="reference.html#variant.concepts.bounded-type" title="BoundedType">bounded types</a>).</p> |
|---|
| 65 | <p>The central difficulty emerges in the details of |
|---|
| 66 | <code class="computeroutput">variant</code> assignment. Given two instances <code class="computeroutput">v1</code> |
|---|
| 67 | and <code class="computeroutput">v2</code> of some concrete <code class="computeroutput">variant</code> type, there |
|---|
| 68 | are two distinct, fundamental cases we must consider for the assignment |
|---|
| 69 | <code class="computeroutput">v1 = v2</code>.</p> |
|---|
| 70 | <p>First consider the case that <code class="computeroutput">v1</code> and <code class="computeroutput">v2</code> |
|---|
| 71 | each contains a value of the same type. Call this type <code class="computeroutput">T</code>. |
|---|
| 72 | In this situation, assignment is perfectly straightforward: use |
|---|
| 73 | <code class="computeroutput">T::operator=</code>.</p> |
|---|
| 74 | <p>However, we must also consider the case that <code class="computeroutput">v1</code> and |
|---|
| 75 | <code class="computeroutput">v2</code> contain values <span class="emphasis"><em>of distinct types</em></span>. |
|---|
| 76 | Call these types <code class="computeroutput">T</code> and <code class="computeroutput">U</code>. At this point, |
|---|
| 77 | since <code class="computeroutput">variant</code> manages its content on the stack, the |
|---|
| 78 | left-hand side of the assignment (i.e., <code class="computeroutput">v1</code>) must destroy |
|---|
| 79 | its content so as to permit in-place copy-construction of the content |
|---|
| 80 | of the right-hand side (i.e., <code class="computeroutput">v2</code>). In the end, whereas |
|---|
| 81 | <code class="computeroutput">v1</code> began with content of type <code class="computeroutput">T</code>, it ends |
|---|
| 82 | with content of type <code class="computeroutput">U</code>, namely a copy of the content of |
|---|
| 83 | <code class="computeroutput">v2</code>.</p> |
|---|
| 84 | <p>The crux of the problem, then, is this: in the event that |
|---|
| 85 | copy-construction of the content of <code class="computeroutput">v2</code> fails, how can |
|---|
| 86 | <code class="computeroutput">v1</code> maintain its "never-empty" guarantee? |
|---|
| 87 | By the time copy-construction from <code class="computeroutput">v2</code> is attempted, |
|---|
| 88 | <code class="computeroutput">v1</code> has already destroyed its content!</p> |
|---|
| 89 | </div> |
|---|
| 90 | <div class="section" lang="en"> |
|---|
| 91 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 92 | <a name="variant.design.never-empty.memcpy-solution"></a>The "Ideal" Solution: False Hopes</h5></div></div></div> |
|---|
| 93 | <p>Upon learning of this dilemma, clever individuals may propose the |
|---|
| 94 | following scheme hoping to solve the problem: |
|---|
| 95 | |
|---|
| 96 | </p> |
|---|
| 97 | <div class="orderedlist"><ol type="1"> |
|---|
| 98 | <li>Provide some "backup" storage, appropriately |
|---|
| 99 | aligned, capable of holding values of the contained type of the |
|---|
| 100 | left-hand side.</li> |
|---|
| 101 | <li>Copy the memory (e.g., using <code class="computeroutput">memcpy</code>) of the |
|---|
| 102 | storage of the left-hand side to the backup storage.</li> |
|---|
| 103 | <li>Attempt a copy of the right-hand side content to the |
|---|
| 104 | (now-replicated) left-hand side storage.</li> |
|---|
| 105 | <li>In the event of an exception from the copy, restore the |
|---|
| 106 | backup (i.e., copy the memory from the backup storage back into |
|---|
| 107 | the left-hand side storage).</li> |
|---|
| 108 | <li>Otherwise, in the event of success, now copy the memory |
|---|
| 109 | of the left-hand side storage to another "temporary" |
|---|
| 110 | aligned storage.</li> |
|---|
| 111 | <li>Now restore the backup (i.e., again copying the memory) |
|---|
| 112 | to the left-hand side storage; with the "old" content |
|---|
| 113 | now restored, invoke the destructor of the contained type on the |
|---|
| 114 | storage of the left-hand side.</li> |
|---|
| 115 | <li>Finally, copy the memory of the temporary storage to the |
|---|
| 116 | (now-empty) storage of the left-hand side.</li> |
|---|
| 117 | </ol></div> |
|---|
| 118 | <p>While complicated, it appears such a scheme could provide the |
|---|
| 119 | desired safety in a relatively efficient manner. In fact, several |
|---|
| 120 | early iterations of the library implemented this very approach.</p> |
|---|
| 121 | <p>Unfortunately, as Dave Abraham's first noted, the scheme results |
|---|
| 122 | in undefined behavior: |
|---|
| 123 | |
|---|
| 124 | </p> |
|---|
| 125 | <div class="blockquote"><blockquote class="blockquote"> |
|---|
| 126 | <p>"That's a lot of code to read through, but if it's |
|---|
| 127 | doing what I think it's doing, it's undefined behavior.</p> |
|---|
| 128 | <p>"Is the trick to move the bits for an existing object |
|---|
| 129 | into a buffer so we can tentatively construct a new object in |
|---|
| 130 | that memory, and later move the old bits back temporarily to |
|---|
| 131 | destroy the old object?</p> |
|---|
| 132 | <p>"The standard does not give license to do that: only one |
|---|
| 133 | object may have a given address at a time. See 3.8, and |
|---|
| 134 | particularly paragraph 4."</p> |
|---|
| 135 | </blockquote></div> |
|---|
| 136 | <p>Additionally, as close examination quickly reveals, the scheme has |
|---|
| 137 | the potential to create irreconcilable race-conditions in concurrent |
|---|
| 138 | environments.</p> |
|---|
| 139 | <p>Ultimately, even if the above scheme could be made to work on |
|---|
| 140 | certain platforms with particular compilers, it is still necessary to |
|---|
| 141 | find a portable solution.</p> |
|---|
| 142 | </div> |
|---|
| 143 | <div class="section" lang="en"> |
|---|
| 144 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 145 | <a name="variant.design.never-empty.double-storage-solution"></a>An Initial Solution: Double Storage</h5></div></div></div> |
|---|
| 146 | <p>Upon learning of the infeasibility of the above scheme, Anthony |
|---|
| 147 | Williams proposed in |
|---|
| 148 | <a href="refs.html#variant.refs.wil02">[Wil02]</a> a scheme that served |
|---|
| 149 | as the basis for a portable solution in some pre-release |
|---|
| 150 | implementations of <code class="computeroutput">variant</code>.</p> |
|---|
| 151 | <p>The essential idea to this scheme, which shall be referred to as |
|---|
| 152 | the "double storage" scheme, is to provide enough space |
|---|
| 153 | within a <code class="computeroutput">variant</code> to hold two separate values of any of |
|---|
| 154 | the bounded types.</p> |
|---|
| 155 | <p>With the secondary storage, a copy the right-hand side can be |
|---|
| 156 | attempted without first destroying the content of the left-hand side; |
|---|
| 157 | accordingly, the content of the left-hand side remains available in |
|---|
| 158 | the event of an exception.</p> |
|---|
| 159 | <p>Thus, with this scheme, the <code class="computeroutput">variant</code> implementation |
|---|
| 160 | needs only to keep track of which storage contains the content -- and |
|---|
| 161 | dispatch any visitation requests, queries, etc. accordingly.</p> |
|---|
| 162 | <p>The most obvious flaw to this approach is the space overhead |
|---|
| 163 | incurred. Though some optimizations could be applied in special cases |
|---|
| 164 | to eliminate the need for double storage -- for certain bounded types |
|---|
| 165 | or in some cases entirely (see |
|---|
| 166 | <a href="design.html#variant.design.never-empty.optimizations" title="Enabling Optimizations">the section called “Enabling Optimizations”</a> for more |
|---|
| 167 | details) -- many users on the Boost mailing list strongly objected to |
|---|
| 168 | the use of double storage. In particular, it was noted that the |
|---|
| 169 | overhead of double storage would be at play at all times -- even if |
|---|
| 170 | assignment to <code class="computeroutput">variant</code> never occurred. For this reason |
|---|
| 171 | and others, a new approach was developed.</p> |
|---|
| 172 | </div> |
|---|
| 173 | <div class="section" lang="en"> |
|---|
| 174 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 175 | <a name="variant.design.never-empty.heap-backup-solution"></a>Current Approach: Temporary Heap Backup</h5></div></div></div> |
|---|
| 176 | <p>Despite the many objections to the double storage solution, it was |
|---|
| 177 | realized that no replacement would be without drawbacks. Thus, a |
|---|
| 178 | compromise was desired.</p> |
|---|
| 179 | <p>To this end, Dave Abrahams suggested to include the following in |
|---|
| 180 | the behavior specification for <code class="computeroutput">variant</code> assignment: |
|---|
| 181 | "<code class="computeroutput">variant</code> assignment from one type to another may |
|---|
| 182 | incur dynamic allocation." That is, while <code class="computeroutput">variant</code> would |
|---|
| 183 | continue to store its content <span class="emphasis"><em>in situ</em></span> after |
|---|
| 184 | construction and after assignment involving identical contained types, |
|---|
| 185 | <code class="computeroutput">variant</code> would store its content on the heap after |
|---|
| 186 | assignment involving distinct contained types.</p> |
|---|
| 187 | <p>The algorithm for assignment would proceed as follows: |
|---|
| 188 | |
|---|
| 189 | </p> |
|---|
| 190 | <div class="orderedlist"><ol type="1"> |
|---|
| 191 | <li>Copy-construct the content of the right-hand side to the |
|---|
| 192 | heap; call the pointer to this data <code class="computeroutput">p</code>.</li> |
|---|
| 193 | <li>Destroy the content of the left-hand side.</li> |
|---|
| 194 | <li>Copy <code class="computeroutput">p</code> to the left-hand side |
|---|
| 195 | storage.</li> |
|---|
| 196 | </ol></div> |
|---|
| 197 | <p> |
|---|
| 198 | |
|---|
| 199 | Since all operations on pointers are nothrow, this scheme would allow |
|---|
| 200 | <code class="computeroutput">variant</code> to meet its never-empty guarantee. |
|---|
| 201 | </p> |
|---|
| 202 | <p>The most obvious concern with this approach is that while it |
|---|
| 203 | certainly eliminates the space overhead of double storage, it |
|---|
| 204 | introduces the overhead of dynamic-allocation to <code class="computeroutput">variant</code> |
|---|
| 205 | assignment -- not just in terms of the initial allocation but also |
|---|
| 206 | as a result of the continued storage of the content on the heap. While |
|---|
| 207 | the former problem is unavoidable, the latter problem may be avoided |
|---|
| 208 | with the following "temporary heap backup" technique: |
|---|
| 209 | |
|---|
| 210 | </p> |
|---|
| 211 | <div class="orderedlist"><ol type="1"> |
|---|
| 212 | <li>Copy-construct the content of the |
|---|
| 213 | <span class="emphasis"><em>left</em></span>-hand side to the heap; call the pointer to |
|---|
| 214 | this data <code class="computeroutput">backup</code>.</li> |
|---|
| 215 | <li>Destroy the content of the left-hand side.</li> |
|---|
| 216 | <li>Copy-construct the content of the right-hand side in the |
|---|
| 217 | (now-empty) storage of the left-hand side.</li> |
|---|
| 218 | <li>In the event of failure, copy <code class="computeroutput">backup</code> to the |
|---|
| 219 | left-hand side storage.</li> |
|---|
| 220 | <li>In the event of success, deallocate the data pointed to |
|---|
| 221 | by <code class="computeroutput">backup</code>.</li> |
|---|
| 222 | </ol></div> |
|---|
| 223 | <p>With this technique: 1) only a single storage is used; |
|---|
| 224 | 2) allocation is on the heap in the long-term only if the assignment |
|---|
| 225 | fails; and 3) after any <span class="emphasis"><em>successful</em></span> assignment, |
|---|
| 226 | storage within the <code class="computeroutput">variant</code> is guaranteed. For the |
|---|
| 227 | purposes of the initial release of the library, these characteristics |
|---|
| 228 | were deemed a satisfactory compromise solution.</p> |
|---|
| 229 | <p>There remain notable shortcomings, however. In particular, there |
|---|
| 230 | may be some users for which heap allocation must be avoided at all |
|---|
| 231 | costs; for other users, any allocation may need to occur via a |
|---|
| 232 | user-supplied allocator. These issues will be addressed in the future |
|---|
| 233 | (see <a href="design.html#variant.design.never-empty.roadmap" title="Future Direction: Policy-based Implementation">the section called “Future Direction: Policy-based Implementation”</a>). For now, |
|---|
| 234 | though, the library treats storage of its content as an implementation |
|---|
| 235 | detail. Nonetheless, as described in the next section, there |
|---|
| 236 | <span class="emphasis"><em>are</em></span> certain things the user can do to ensure the |
|---|
| 237 | greatest efficiency for <code class="computeroutput">variant</code> instances (see |
|---|
| 238 | <a href="design.html#variant.design.never-empty.optimizations" title="Enabling Optimizations">the section called “Enabling Optimizations”</a> for |
|---|
| 239 | details).</p> |
|---|
| 240 | </div> |
|---|
| 241 | <div class="section" lang="en"> |
|---|
| 242 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 243 | <a name="variant.design.never-empty.optimizations"></a>Enabling Optimizations</h5></div></div></div> |
|---|
| 244 | <p>As described in |
|---|
| 245 | <a href="design.html#variant.design.never-empty.problem" title="The Implementation Problem">the section called “The Implementation Problem”</a>, the central |
|---|
| 246 | difficulty in implementing the never-empty guarantee is the |
|---|
| 247 | possibility of failed copy-construction during <code class="computeroutput">variant</code> |
|---|
| 248 | assignment. Yet types with nothrow copy constructors clearly never |
|---|
| 249 | face this possibility. Similarly, if one of the bounded types of the |
|---|
| 250 | <code class="computeroutput">variant</code> is nothrow default-constructible, then such a |
|---|
| 251 | type could be used as a safe "fallback" type in the event of |
|---|
| 252 | failed copy construction.</p> |
|---|
| 253 | <p>Accordingly, <code class="computeroutput">variant</code> is designed to enable the |
|---|
| 254 | following optimizations once the following criteria on its bounded |
|---|
| 255 | types are met: |
|---|
| 256 | |
|---|
| 257 | </p> |
|---|
| 258 | <div class="itemizedlist"><ul type="disc"> |
|---|
| 259 | <li>For each bounded type <code class="computeroutput">T</code> that is nothrow |
|---|
| 260 | copy-constructible (as indicated by |
|---|
| 261 | <code class="computeroutput">boost::has_nothrow_copy</code>), the |
|---|
| 262 | library guarantees <code class="computeroutput">variant</code> will use only single |
|---|
| 263 | storage and in-place construction for <code class="computeroutput">T</code>.</li> |
|---|
| 264 | <li>If <span class="emphasis"><em>any</em></span> bounded type is nothrow |
|---|
| 265 | default-constructible (as indicated by |
|---|
| 266 | <code class="computeroutput">boost::has_nothrow_constructor</code>), |
|---|
| 267 | the library guarantees <code class="computeroutput">variant</code> will use only single |
|---|
| 268 | storage and in-place construction for <span class="emphasis"><em>every</em></span> |
|---|
| 269 | bounded type in the <code class="computeroutput">variant</code>. Note, however, that in |
|---|
| 270 | the event of assignment failure, an unspecified nothrow |
|---|
| 271 | default-constructible bounded type will be default-constructed in |
|---|
| 272 | the left-hand side operand so as to preserve the never-empty |
|---|
| 273 | guarantee.</li> |
|---|
| 274 | </ul></div> |
|---|
| 275 | <p><span class="bold"><strong>Caveat</strong></span>: On most platforms, the |
|---|
| 276 | Type Traits templates |
|---|
| 277 | <code class="computeroutput">has_nothrow_copy</code> and <code class="computeroutput">has_nothrow_constructor</code> |
|---|
| 278 | by default return <code class="computeroutput">false</code> for all <code class="computeroutput">class</code> and |
|---|
| 279 | <code class="computeroutput">struct</code> types. It is necessary therefore to provide |
|---|
| 280 | specializations of these templates as appropriate for user-defined |
|---|
| 281 | types, as demonstrated in the following: |
|---|
| 282 | |
|---|
| 283 | </p> |
|---|
| 284 | <pre class="programlisting">// ...in your code (at file scope)... |
|---|
| 285 | |
|---|
| 286 | namespace boost { |
|---|
| 287 | |
|---|
| 288 | template <> |
|---|
| 289 | struct <code class="computeroutput">has_nothrow_copy</code>< myUDT > |
|---|
| 290 | : <code class="computeroutput">mpl::true_</code> |
|---|
| 291 | { |
|---|
| 292 | }; |
|---|
| 293 | |
|---|
| 294 | } |
|---|
| 295 | </pre> |
|---|
| 296 | <p><span class="bold"><strong>Implementation Note</strong></span>: So as to make |
|---|
| 297 | the behavior of <code class="computeroutput">variant</code> more predictable in the aftermath |
|---|
| 298 | of an exception, the current implementation prefers to default-construct |
|---|
| 299 | <code class="computeroutput">boost::blank</code> if specified as a |
|---|
| 300 | bounded type instead of other nothrow default-constructible bounded |
|---|
| 301 | types. (If this is deemed to be a useful feature, it will become part |
|---|
| 302 | of the specification for <code class="computeroutput">variant</code>; otherwise, it may be |
|---|
| 303 | obsoleted. Please provide feedback to the Boost mailing list.)</p> |
|---|
| 304 | </div> |
|---|
| 305 | <div class="section" lang="en"> |
|---|
| 306 | <div class="titlepage"><div><div><h5 class="title"> |
|---|
| 307 | <a name="variant.design.never-empty.roadmap"></a>Future Direction: Policy-based Implementation</h5></div></div></div> |
|---|
| 308 | <p>As the previous sections have demonstrated, much effort has been |
|---|
| 309 | expended in an attempt to provide a balance between performance, data |
|---|
| 310 | size, and heap usage. Further, significant optimizations may be |
|---|
| 311 | enabled in <code class="computeroutput">variant</code> on the basis of certain traits of its |
|---|
| 312 | bounded types.</p> |
|---|
| 313 | <p>However, there will be some users for whom the chosen compromise |
|---|
| 314 | is unsatisfactory (e.g.: heap allocation must be avoided at all costs; |
|---|
| 315 | if heap allocation is used, custom allocators must be used; etc.). For |
|---|
| 316 | this reason, a future version of the library will support a |
|---|
| 317 | policy-based implementation of <code class="computeroutput">variant</code>. While this will |
|---|
| 318 | not eliminate the problems described in the previous sections, it will |
|---|
| 319 | allow the decisions regarding tradeoffs to be decided by the user |
|---|
| 320 | rather than the library designers.</p> |
|---|
| 321 | </div> |
|---|
| 322 | </div> |
|---|
| 323 | </div> |
|---|
| 324 | <table width="100%"><tr> |
|---|
| 325 | <td align="left"></td> |
|---|
| 326 | <td align="right"><small>Copyright © 2002, 2003 Eric Friedman, Itay Maman</small></td> |
|---|
| 327 | </tr></table> |
|---|
| 328 | <hr> |
|---|
| 329 | <div class="spirit-nav"> |
|---|
| 330 | <a accesskey="p" href="../visitor_ptr.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../variant.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="misc.html"><img src="../images/next.png" alt="Next"></a> |
|---|
| 331 | </div> |
|---|
| 332 | </body> |
|---|
| 333 | </html> |
|---|