1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN"> 2 3<html> 4<head> 5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 6<title>Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight</title> 7<link rel="stylesheet" href="../style.css" type="text/css"> 8<link rel="start" href="../index.html"> 9<link rel="prev" href="configuration.html"> 10<link rel="up" href="index.html"> 11<link rel="next" href="technical.html"> 12</head> 13 14<body> 15<h1><img src="../../../../boost.png" alt="Boost logo" align= 16"middle" width="277" height="86">Boost.Flyweight Tutorial: Extending Boost.Flyweight</h1> 17 18<div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br> 19Configuring Boost.Flyweight 20</a></div> 21<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> 22Boost.Flyweight tutorial 23</a></div> 24<div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br> 25Technical issues 26</a></div><br clear="all" style="clear: all;"> 27 28<hr> 29 30<h2>Contents</h2> 31 32<ul> 33 <li><a href="#intro">Introduction</a></li> 34 <li><a href="#factories">Custom factories</a></li> 35 <li><a href="#holders">Custom holders</a></li> 36 <li><a href="#locking">Custom locking policies</a></li> 37 <li><a href="#tracking">Custom tracking policies</a></li> 38</ul> 39 40<h2><a name="intro">Introduction</a></h2> 41 42<p> 43Boost.Flyweight provides public interface specifications of 44its <a href="configuration.html">configurable aspects</a> so that the user 45can extend the library by implementing her own components and providing them to 46instantiations of the <code>flyweight</code> class template. 47</p> 48 49<p> 50In most cases there are two types of entities involved in extending a given 51aspect of Boost.Flyweight: 52<ul> 53 <li>The component itself (for instance, a factory class template).</li> 54 <li>The associated <i>component specifier</i>, which is the type 55 provided as a template argument of a <code>flyweight</code> 56 instantiation. 57 </li> 58</ul> 59For example, the type 60<a href="configuration.html#static_holder"><code>static_holder</code></a> 61is a holder specifier which is used by <code>flyweight</code> to generate 62actual holder classes, in this case instantiations of the class 63template 64<a href="../reference/holders.html#static_holder_class"><code>static_holder_class</code></a>. 65Note that <code>static_holder</code> is a concrete type while 66<code>static_holder_class</code> is a class template, so a specifier can be 67seen as a convenient way to provide access to a family of related concrete 68components (the different possible instantiations of the class template): 69<code>flyweight</code> internally selects the particular component 70appropriate for its internal needs. 71</p> 72 73<h2><a name="factories">Custom factories</a></h2> 74 75<p> 76In a way, factories resemble unique associative containers like <code>std::set</code>, 77though their expected interface is much more concise: 78</p> 79 80<blockquote><pre> 81<span class=comment>// example of a possible factory class template</span> 82 83<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>></span> 84<span class=keyword>class</span> <span class=identifier>custom_factory_class</span> 85<span class=special>{</span> 86<span class=keyword>public</span><span class=special>:</span> 87 <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>handle_type</span><span class=special>;</span> 88 89 <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span> 90 <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> 91 <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>);</span> 92<span class=special>};</span> 93</pre></blockquote> 94 95<p> 96Factories are parameterized by <code>Entry</code> and <code>Key</code>: 97the first is the type of the objects stored, while the second is the public 98key type on which <code>flyweight</code> operates (e.g. the <code>std::string</code> 99in <code>flyweight<std::string></code> or 100<code>flyweight<key_value<std::string,texture> ></code>). An entry holds a 101shared value to which flyweight objects are associated as well as internal bookkeeping information, but from the 102point of view of the factory, though, the only fact known about <code>Entry</code> 103is that it is implicitly convertible to <code>const Key&</code>, and it is 104based on their associated <code>Key</code> that entries are to be considered 105equivalent or not. The factory <code>insert()</code> 106member function locates a previously stored entry whose 107associated <code>Key</code> is equivalent to that of the <code>Entry</code> 108object being passed (for some equivalence relation on <code>Key</code> germane to 109the factory), or stores the new entry if no equivalent one is found. A 110<code>handle_type</code> to the equivalent or newly inserted entry is returned; 111this <code>handle_type</code> is a token for further access to an entry via 112<code>erase()</code> and <code>entry()</code>. Consult the 113<a href="../reference/factories.html#factory">reference</a> for the formal 114definition of the <code>Factory</code> concept. 115</p> 116 117<p> 118Let us see an actual example of realization of a custom factory class. Suppose 119we want to trace the different invocations by Boost.Flyweight of the 120<code>insert()</code> and <code>erase()</code> member functions: this can be 121done by using a custom factory whose member methods emit trace messages 122to the program console. We base the implementation of the repository 123functionality on a regular <code>std::set</code>: 124 125<blockquote><pre> 126<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Key</span><span class=special>></span> 127<span class=keyword>class</span> <span class=identifier>verbose_factory_class</span> 128<span class=special>{</span> 129 <span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>></span> <span class=identifier>store_type</span><span class=special>;</span> 130 131 <span class=identifier>store_type</span> <span class=identifier>store</span><span class=special>;</span> 132 133<span class=keyword>public</span><span class=special>:</span> 134 <span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>store_type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>handle_type</span><span class=special>;</span> 135 136 <span class=identifier>handle_type</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>x</span><span class=special>)</span> 137 <span class=special>{</span> 138 <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>handle_type</span><span class=special>,</span> <span class=keyword>bool</span><span class=special>></span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>store</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span> 139 <span class=keyword>if</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){</span> <span class=comment>/* new entry */</span> 140 <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"new: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> 141 <span class=special>}</span> 142 <span class=keyword>else</span><span class=special>{</span> <span class=comment>/* existing entry */</span> 143 <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"hit: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)</span><span class=identifier>x</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> 144 <span class=special>}</span> 145 <span class=keyword>return</span> <span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span> 146 <span class=special>}</span> 147 148 <span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span> 149 <span class=special>{</span> 150 <span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special><<</span><span class=string>"del: "</span><span class=special><<(</span><span class=keyword>const</span> <span class=identifier>Key</span><span class=special>&)*</span><span class=identifier>h</span><span class=special><<</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span> 151 <span class=identifier>store</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>h</span><span class=special>);</span> 152 <span class=special>}</span> 153 154 <span class=keyword>const</span> <span class=identifier>Entry</span><span class=special>&</span> <span class=identifier>entry</span><span class=special>(</span><span class=identifier>handle_type</span> <span class=identifier>h</span><span class=special>)</span> 155 <span class=special>{</span> 156 <span class=keyword>return</span> <span class=special>*</span><span class=identifier>h</span><span class=special>;</span> 157 <span class=special>}</span> 158<span class=special>};</span> 159</pre></blockquote> 160 161<p> 162The code deserves some commentaries: 163<ul> 164 <li> 165 Note that the factory is parameterized by <code>Entry</code> 166 and <code>Key</code>, as these types are provided internally by Boost.Flyweight 167 when the factory is instantiated as part of the machinery of <code>flyeight</code>; 168 but there is nothing to prevent us from having more template parameters for 169 finer configuration of the factory type: for instance, we could extend 170 <code>verbose_factory_class</code> to accept some comparison predicate rather than 171 the default <code>std::less<Key></code>, or to specify the allocator 172 used by the internal <code>std::set</code>. 173 </li> 174 <li> 175 The fact that <code>Entry</code> is convertible to <code>const Key&</code> 176 (which is about the only property known about <code>Entry</code>) is 177 exploited in the specification of <code>std::less<Key></code> as 178 the comparison predicate for the <code>std::set</code> of <code>Entry</code>s 179 used as the internal repository. 180 </li> 181 <li> 182 As our public <code>handle_type</code> we are simply using an iterator to the 183 internal <code>std::set</code>. 184 </li> 185</ul> 186</p> 187 188<p> 189In order to plug a custom factory into the specification of a <code>flyweight</code> 190type, we need an associated construct called the <i>factory specifier</i>. 191A factory specifier is a 192<a href="lambda_expressions.html"><code>Lambda 193Expression</code></a> accepting the two argument types <code>Entry</code> 194and <code>Key</code> and returning the corresponding factory class: 195</p> 196 197<blockquote><pre> 198<span class=comment>// Factory specifier (metafunction class version)</span> 199 200<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span> 201<span class=special>{</span> 202 <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> 203 <span class=keyword>struct</span> <span class=identifier>apply</span> 204 <span class=special>{</span> 205 <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> 206 <span class=special>}</span> 207<span class=special>};</span> 208 209<span class=comment>// Factory specifier (placeholder version)</span> 210 211<span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span> 212 <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>,</span> 213 <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_2</span> 214<span class=special>></span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span> 215</pre></blockquote> 216 217<p> 218There is one last detail: in order to implement <code>flyweight</code> 219<a href="configuration.html#free_order_template">free-order template 220parameter interface</a>, it is necessary to explicitly tag a 221factory specifier as such, so that it can be distinguised from other 222types of specifiers. Boost.Flyweight provides three different mechanisms 223to do this tagging: 224<ol> 225 <li>Have the specifier derive from the dummy type <code>factory_marker</code>. 226 Note that this mechanism cannot be used with placeholder expressions. 227<blockquote><pre> 228<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 229 230<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>:</span> <span class=identifier><b>factory_marker</b></span> 231<span class=special>{</span> 232 <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> 233 <span class=keyword>struct</span> <span class=identifier>apply</span> 234 <span class=special>{</span> 235 <span class=keyword>typedef</span> <span class=identifier>custom_factory_class</span><span class=special><</span><span class=identifier>Entry</span><span class=special>,</span><span class=identifier>Key</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> 236 <span class=special>}</span> 237<span class=special>};</span> 238</pre></blockquote> 239 </li> 240 <li>Specialize a special class template called 241 <a href="../reference/factories.html#is_factory"><code>is_factory</code></a>: 242<blockquote><pre> 243<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 244 245<span class=keyword>struct</span> <span class=identifier>custom_factory_specifier</span><span class=special>{};</span> 246 247<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> 248<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> 249 250<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_factory</span><span class=special><</span><span class=identifier>custom_factory_specifier</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> 251 252<span class=special>}</span> 253<span class=special>}</span> 254</pre></blockquote> 255 </li> 256 <li>The third mechanism, which is the least intrusive, consists in 257 wrapping the specifier inside the 258 <a href="../reference/factories.html#factory_construct"><code>factory</code></a> 259 construct: 260<blockquote><pre> 261<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>factory_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 262 263<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> 264 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> 265 <span class=identifier><b>factory</b></span><span class=special><</span><span class=identifier>custom_factory_specifier</span><span class=special>></span> 266<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> 267</pre></blockquote> 268 </li> 269</ol> 270</p> 271 272<p> 273<a href="../examples.html#example8">Example 8</a> in the examples section develops 274in full the <code>verbose_factory_class</code> case sketched above. 275</p> 276 277<h2><a name="holders">Custom holders</a></h2> 278 279<p> 280A holder is a class with a static member function <code>get()</code> giving 281access to a unique instance of a given type <code>C</code>: 282</p> 283 284<blockquote><pre> 285<span class=comment>// example of a possible holder class template</span> 286 287<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> 288<span class=keyword>class</span> <span class=identifier>custom_holder_class</span> 289<span class=special>{</span> 290<span class=keyword>public</span><span class=special>:</span> 291 <span class=keyword>static</span> <span class=identifier>C</span><span class=special>&</span> <span class=identifier>get</span><span class=special>();</span> 292<span class=special>};</span> 293</pre></blockquote> 294 295<p> 296<code>flyweight</code> internally uses a holder to create its associated 297factory as well as some other global data. A holder specifier is a 298<a href="lambda_expressions.html"><code>Lambda 299Expression</code></a> accepting the type <code>C</code> upon which 300the associated holder class operates: 301</p> 302 303<blockquote><pre> 304<span class=comment>// Holder specifier (metafunction class version)</span> 305 306<span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span> 307<span class=special>{</span> 308 <span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>C</span><span class=special>></span> 309 <span class=keyword>struct</span> <span class=identifier>apply</span> 310 <span class=special>{</span> 311 <span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special><</span><span class=identifier>C</span><span class=special>></span> <span class=identifier>type</span><span class=special>;</span> 312 <span class=special>}</span> 313<span class=special>};</span> 314 315<span class=comment>// Holder specifier (placeholder version)</span> 316 317<span class=keyword>typedef</span> <span class=identifier>custom_holder_class</span><span class=special><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>_1</span><span class=special>></span> <span class=identifier>custom_factory_specifier</span><span class=special>;</span> 318</pre></blockquote> 319 320<p> 321As is the case with <a href="#factories">factory specifiers</a>, holder 322specifiers must be tagged in order to be properly recognized when 323provided to <code>flyweight</code>, and there are three available mechanisms 324to do so: 325</p> 326 327<blockquote><pre> 328<span class=comment>// Alternatives for tagging a holder specifier</span> 329 330<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>holder_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 331 332<span class=comment>// 1: Have the specifier derive from holder_marker</span> 333 334<span class=keyword>struct</span> <span class=identifier>custom_holder_specifier</span><span class=special>:</span> <span class=identifier><b>holder_marker</b></span> 335<span class=special>{</span> 336 <span class=special>...</span> 337<span class=special>};</span> 338 339<span class=comment>// 2: Specialize the is_holder class template</span> 340 341<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> 342<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> 343 344<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_holder</span><span class=special><</span><span class=identifier>custom_holder_specifier</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> 345 346<span class=special>}}</span> 347 348<span class=comment>// 3: use the holder<> wrapper when passing the specifier 349// to flyweight</span> 350 351<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> 352 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> 353 <span class=identifier><b>holder</b></span><span class=special><</span><span class=identifier>custom_holder_specifier</span><span class=special>></span> 354<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> 355</pre></blockquote> 356 357<h2><a name="locking">Custom locking policies</a></h2> 358 359<p> 360A custom locking policy presents the following simple interface: 361</p> 362 363<blockquote><pre> 364<span class=comment>// example of a custom policy</span> 365 366<span class=keyword>class</span> <span class=identifier>custom_locking</span> 367<span class=special>{</span> 368 <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>mutex_type</span><span class=special>;</span> 369 <span class=keyword>typedef</span> <span class=special>...</span> <span class=identifier>lock_type</span><span class=special>;</span> 370<span class=special>};</span> 371</pre></blockquote> 372 373<p> 374where <code>lock_type</code> is used to acquire/release mutexes according to 375the <i>scoped lock</i> idiom: 376</p> 377 378<blockquote><pre> 379<span class=identifier>mutex_type</span> <span class=identifier>m</span><span class=special>;</span> 380<span class=special>...</span> 381<span class=special>{</span> 382 <span class=identifier>lock_type</span> <span class=identifier>lk</span><span class=special>(</span><span class=identifier>m</span><span class=special>);</span> <span class=comment>// acquire the mutex 383 // zone of mutual exclusion, no other thread can acquire the mutex</span> 384 <span class=special>...</span> 385<span class=special>}</span> <span class=comment>// m released at lk destruction</span> 386</pre></blockquote> 387 388<p> 389Formal definitions for the concepts 390<a href="../reference/locking.html#preliminary"><code>Mutex</code></a> and 391<a href="../reference/locking.html#preliminary"><code>Scoped Lock</code></a> 392are given at the reference. To pass a locking policy as a template argument of 393<code>flyweight</code>, the class must be appropriately tagged: 394</p> 395 396<blockquote><pre> 397<span class=comment>// Alternatives for tagging a locking policy</span> 398 399<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>locking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 400 401<span class=comment>// 1: Have the policy derive from locking_marker</span> 402 403<span class=keyword>struct</span> <span class=identifier>custom_locking</span><span class=special>:</span> <span class=identifier>locking_marker</span> 404<span class=special>{</span> 405 <span class=special>...</span> 406<span class=special>};</span> 407 408<span class=comment>// 2: Specialize the is_locking class template</span> 409 410<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> 411<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> 412 413<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_locking</span><span class=special><</span><span class=identifier>custom_locking</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> 414 415<span class=special>}}</span> 416 417<span class=comment>// 3: use the locking<> wrapper when passing the policy 418// to flyweight</span> 419 420<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> 421 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> 422 <span class=identifier>locking</span><span class=special><</span><span class=identifier>custom_locking</span><span class=special>></span> 423<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> 424</pre></blockquote> 425 426<p> 427Note that a locking policy is its own specifier, i.e. there is no 428additional class to be passed as a proxy for the real component as is 429the case with factories and holders. 430</p> 431 432<h2><a name="tracking">Custom tracking policies</a></h2> 433 434<p> 435Tracking policies contribute some type information to the process of 436definition of the internal flyweight factory, and are given access 437to that factory to allow for the implementation of the tracking 438code. A tracking policy <code>Tracking</code> is defined as a class with 439the following nested elements: 440<ul> 441 <li>A type <code>Tracking::entry_type</code>.</li> 442 <li>A type <code>Tracking::handle_type</code>.</li> 443</ul> 444Each of these elements build on the preceding one, in the sense that 445Boost.Flyweight internal machinery funnels the results produced by an 446element into the following: 447<ul> 448 <li><code>Tracking::entry_type</code> is a 449 <a href="lambda_expressions.html"><code>Lambda 450 Expression</code></a> accepting two different types named 451 <code>Value</code> and <code>Key</code> such that 452 <code>Value</code> is implicitly convertible to 453 <code>const Key&</code>. The expression is expected 454 to return 455 a type implicitly convertible to both <code>const Value&</code> 456 and <code>const Key&</code>. 457 <code>Tracking::entry_type</code> corresponds to the actual 458 type of the entries stored into the 459 <a href="configuration.html#factory_types">flyweight factory</a>: 460 by allowing the tracking policy to take part on the definition 461 of this type it is possible for the policy to add internal 462 tracking information to the entry data in case this is needed. 463 If no additional information is required, 464 the tracking policy can simply return <code>Value</code> as its 465 <code>Tracking::entry_type</code> type. 466 </li> 467 <li> 468 The binary <a href="lambda_expressions.html"><code>Lambda 469 Expression</code></a> <code>Tracking::handle_type</code> is invoked 470 with types <code>InternalHandle</code> and <code>TrackingHandler</code> 471 to produce a type <code>Handle</code>, which will be used as the handle 472 type of the flyweight factory. 473 <a href="../reference/tracking.html#preliminary"><code>TrackingHandler</code></a> 474 is passed as a template argument to <code>Tracking::handle_type</code> 475 to offer functionality supporting the implementation of the tracking 476 code. 477 </li> 478</ul> 479So, in order to define the factory of some instantiation 480<code>fw_t</code> of <code>flyweight</code>, <code>Tracking::entry_type</code> 481is invoked with an internal type <code>Value</code> implicitly convertible 482to <code>const fw_t::key_type&</code> to obtain the entry type for the factory, 483which must be convertible to both <code>const Value&</code> and 484<code>const fw_t::key_type&</code>. 485Then, <code>Tracking::handle_type</code> is fed an internal handle 486type and a tracking policy helper to produce the factory handle type. 487The observant reader might have detected an apparent circularity: 488<code>Tracking::handle_type</code> produces the handle type of 489the flyweight factory, and at the same time is passed a tracking helper 490that grants access to the factory being defined! 491The solution to this riddle comes from the realization of the fact that 492<code>TrackingHandler</code> is an <i>incomplete 493type</i> by the time it is passed to <code>Tracking::handle_type</code>: 494only when <code>Handle</code> is instantiated at a later stage will this 495type be complete. 496</p> 497 498<p> 499In order for a tracking policy to be passed to <code>flyweight</code>, 500it must be tagged much in the same way as the rest of specifiers. 501</p> 502 503<blockquote><pre> 504<span class=comment>// Alternatives for tagging a tracking policy</span> 505 506<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>flyweight</span><span class=special>/</span><span class=identifier>tracking_tag</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span> 507 508<span class=comment>// 1: Have the policy derive from tracking_marker</span> 509 510<span class=keyword>struct</span> <span class=identifier>custom_tracking</span><span class=special>:</span> <span class=identifier><b>tracking_marker</b></span> 511<span class=special>{</span> 512 <span class=special>...</span> 513<span class=special>};</span> 514 515<span class=comment>// 2: Specialize the is_tracking class template</span> 516 517<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span> 518<span class=keyword>namespace</span> <span class=identifier>flyweights</span><span class=special>{</span> 519 520<span class=keyword>template</span><span class=special><></span> <span class=keyword>struct</span> <span class=identifier>is_tracking</span><span class=special><</span><span class=identifier>custom_tracking</span><span class=special>>:</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>true_</span><span class=special>{};</span> 521 522<span class=special>}}</span> 523 524<span class=comment>// 3: use the tracking<> wrapper when passing the policy 525// to flyweight</span> 526 527<span class=keyword>typedef</span> <span class=identifier>flyweight</span><span class=special><</span> 528 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span> 529 <span class=identifier><b>tracking</b></span><span class=special><</span><span class=identifier>custom_tracking</span><span class=special>></span> 530<span class=special>></span> <span class=identifier>flyweight_string</span><span class=special>;</span> 531</pre></blockquote> 532 533<p> 534Tracking policies are their own specifiers, that is, they are provided directly 535as template arguments to the <code>flyweight</code> class template. 536</p> 537 538<hr> 539 540<div class="prev_link"><a href="configuration.html"><img src="../prev.gif" alt="configuring Boost.Flyweight" border="0"><br> 541Configuring Boost.Flyweight 542</a></div> 543<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> 544Boost.Flyweight tutorial 545</a></div> 546<div class="next_link"><a href="technical.html"><img src="../next.gif" alt="technical issues" border="0"><br> 547Technical issues 548</a></div><br clear="all" style="clear: all;"> 549 550<br> 551 552<p>Revised September 1st 2014</p> 553 554<p>© Copyright 2006-2014 Joaquín M López Muñoz. 555Distributed under the Boost Software 556License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> 557LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> 558http://www.boost.org/LICENSE_1_0.txt</a>) 559</p> 560 561</body> 562</html> 563