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 - Basics</title> 7<link rel="stylesheet" href="../style.css" type="text/css"> 8<link rel="start" href="../index.html"> 9<link rel="prev" href="index.html"> 10<link rel="up" href="index.html"> 11<link rel="next" href="key_value.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: Basics</h1> 17 18<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br> 19Boost.Flyweight tutorial 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="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br> 25Key-value flyweights 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> 34 <ul> 35 <li><a href="#serialization">Serialization</a></li> 36 </ul> 37 </li> 38 <li><a href="#requirements">Flyweight requirements</a></li> 39</ul> 40 41<h2><a name="intro">Introduction</a></h2> 42 43<p> 44Suppose we are writing a massive multiplayer online game 45which has to maintain hundreds of thousands or millions of instances 46of the following class in memory: 47</p> 48 49<blockquote><pre> 50<span class=keyword>struct</span> <span class=identifier>user_entry</span> 51<span class=special>{</span> 52 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>first_name</span><span class=special>;</span> 53 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>last_name</span><span class=special>;</span> 54 <span class=keyword>int</span> <span class=identifier>age</span><span class=special>;</span> 55 <span class=special>...</span> 56<span class=special>};</span> 57</pre></blockquote> 58 59<p> 60In this kind of environments memory resources are precious, so we are seeking 61ways to make <code>user_entry</code> as compact as possible. Typically, there 62exists a very high level of repetition of first and last names among 63the community users, so an obvious optimization consists in moving 64<code>user_entry::first_name</code> and <code>user_entry::last_name</code> 65objects to a common repository where duplicates are avoided, and leaving 66references to these inside <code>user_entry</code>. This is precisely what 67Boost.Flyweight does in the simplest possible way for the programmer: 68</p> 69 70<blockquote><pre> 71<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>hpp</span><span class=special>></span> 72 73<span class=keyword>struct</span> <span class=identifier>user_entry</span> 74<span class=special>{</span> 75 <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>first_name</span><span class=special>;</span> 76 <span class=identifier>flyweight</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=identifier>last_name</span><span class=special>;</span> 77 <span class=keyword>int</span> <span class=identifier>age</span><span class=special>;</span> 78 <span class=special>...</span> 79<span class=special>};</span> 80</pre></blockquote> 81 82<p> 83Boost.Flyweight automatically performs the optimization just described behind 84the scenes, so that the net effect of this change is that the memory 85usage of the program decreases by a factor proportional to the level of 86redundancy among user names. 87</p> 88 89<p> 90<code>flyweight<std::string></code> behaves in many ways like 91<code>std::string</code>; for instance, the following code works 92unchanged after the redefinition of <code>user_entry</code>: 93</p> 94 95<blockquote><pre> 96<span class=comment>// flyweight<T> can be constructed in the same way as T objects can, 97// even with multiple argument constructors</span> 98 99<span class=identifier>user_entry</span><span class=special>::</span><span class=identifier>user_entry</span><span class=special>(</span><span class=keyword>const</span> <span class=keyword>char</span><span class=special>*</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=keyword>char</span><span class=special>*</span> <span class=identifier>l</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>a</span><span class=special>,...):</span> 100 <span class=identifier>first_name</span><span class=special>(</span><span class=identifier>f</span><span class=special>),</span> 101 <span class=identifier>last_name</span><span class=special>(</span><span class=identifier>l</span><span class=special>),</span> 102 <span class=identifier>age</span><span class=special>(</span><span class=identifier>a</span><span class=special>),</span> 103 <span class=special>...</span> 104<span class=special>{}</span> 105 106<span class=comment>// flyweight classes have relational operators replicating the 107// semantics of the underyling type</span> 108 109<span class=keyword>bool</span> <span class=identifier>same_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user1</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user2</span><span class=special>)</span> 110<span class=special>{</span> 111 <span class=keyword>return</span> <span class=identifier>user1</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>==</span><span class=identifier>user2</span><span class=special>.</span><span class=identifier>first_name</span> <span class=special>&&</span> 112 <span class=identifier>user1</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>==</span><span class=identifier>user2</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>;</span> 113<span class=special>}</span> 114 115<span class=comment>// flyweight<T> provides operator<< and operator>> internally 116// forwarding to T::operator<< and T::operator>></span> 117 118<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&</span> <span class=keyword>operator</span><span class=special><<(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream</span><span class=special>&</span> <span class=identifier>os</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user</span><span class=special>)</span> 119<span class=special>{</span> 120 <span class=keyword>return</span> <span class=identifier>os</span><span class=special><<</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special><<</span><span class=string>" "</span><span class=special><<</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special><<</span><span class=string>" "</span><span class=special><<</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span> 121<span class=special>}</span> 122 123<span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&</span> <span class=keyword>operator</span><span class=special>>>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>istream</span><span class=special>&</span> <span class=identifier>is</span><span class=special>,</span><span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user</span><span class=special>)</span> 124<span class=special>{</span> 125 <span class=keyword>return</span> <span class=identifier>is</span><span class=special>>></span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>>></span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>>></span><span class=identifier>user</span><span class=special>.</span><span class=identifier>age</span><span class=special>;</span> 126<span class=special>}</span> 127</pre></blockquote> 128 129<p> 130Besides, <code>flyweight<T></code> is convertible to 131<code>const T&</code>, either implicitly or through the <code>get</code> 132member function: 133</p> 134 135<blockquote><pre> 136<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full_name</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user</span><span class=special>)</span> 137<span class=special>{</span> 138 <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>full</span><span class=special>;</span> 139 140 <span class=identifier>full</span><span class=special>.</span><span class=identifier>reserve</span><span class=special>(</span> 141 <span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>.</span><span class=identifier>get</span><span class=special>().</span><span class=identifier>size</span><span class=special>()+</span> <span class=comment>// get() returns the underlying</span> 142 <span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>.</span><span class=identifier>get</span><span class=special>().</span><span class=identifier>size</span><span class=special>()+</span><span class=number>1</span><span class=special>);</span> <span class=comment>// const std::string&</span> 143 144 <span class=identifier>full</span><span class=special>+=</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>;</span> <span class=comment>// implicit conversion is used here</span> 145 <span class=identifier>full</span><span class=special>+=</span><span class=string>" "</span><span class=special>;</span> 146 <span class=identifier>full</span><span class=special>+=</span><span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>;</span> 147 148 <span class=keyword>return</span> <span class=identifier>full</span><span class=special>;</span> 149<span class=special>}</span> 150</pre></blockquote> 151 152<p> 153The most important restriction to take into account when replacing a class 154with an equivalent flyweight is the fact that flyweights are not 155mutable: since several flyweight objects can share the same representation 156value, modifying this value is not admissible. On the other hand, flyweight 157objects can be assigned new values: 158</p> 159 160<blockquote><pre> 161<span class=keyword>void</span> <span class=identifier>change_name</span><span class=special>(</span> 162 <span class=identifier>user_entry</span><span class=special>&</span> <span class=identifier>user</span><span class=special>,</span> 163 <span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&</span> <span class=identifier>l</span><span class=special>)</span> 164<span class=special>{</span> 165 <span class=identifier>user</span><span class=special>.</span><span class=identifier>first_name</span><span class=special>=</span><span class=identifier>f</span><span class=special>;</span> 166 <span class=identifier>user</span><span class=special>.</span><span class=identifier>last_name</span><span class=special>=</span><span class=identifier>l</span><span class=special>;</span> 167<span class=special>}</span> 168</pre></blockquote> 169 170<p> 171In general, <code>flyweight<T></code> interface is designed to make 172the transition from plain <code>T</code> as straightforward as possible. 173Check the <a href="../reference/flyweight.html#flyweight">reference</a> for 174further details on the interface of the class template <code>flyweight</code>. 175The <a href="../examples.html">examples section</a> explores 176some common usage scenarios of Boost.Flyweight. 177</p> 178 179<h4><a name="serialization">Serialization</a></h4> 180 181<p> 182<code>flyweight<T></code> can be serialized by means of the 183<a href="../../../serialization/index.html">Boost Serialization Library</a> 184as long as the underlying <code>T</code> is serializable. Both regular and 185XML archives are supported. In order to 186use Boost.Flyweight serialization capabilities, the specific 187header <a href="../reference/flyweight.html#serialize_synopsis"><code>"boost/flyweight/serialize.hpp"</code></a> 188must be included. 189</p> 190 191<blockquote><pre><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">serialize</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> 192 193<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Archive</span><span class="special">></span> 194<span class="keyword">void</span> <span class="identifier">serialize</span><span class="special">(</span><span class="identifier">Archive</span><span class="special">&</span> <span class="identifier">ar</span><span class="special">,</span><span class="identifier">user_entry</span><span class="special">&</span> <span class="identifier">user</span><span class="special">,</span><span class="keyword">const</span> <span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">)</span> 195<span class="special">{</span> 196 <span class="identifier">ar</span><span class="special">&</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">first_name</span><span class="special">;</span> 197 <span class="identifier">ar</span><span class="special">&</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">last_name</span><span class="special">;</span> 198 <span class="identifier">ar</span><span class="special">&</span><span class="identifier">user</span><span class="special">.</span><span class="identifier">age</span><span class="special">;</span> 199 <span class="special">...</span> 200<span class="special">}</span> 201</pre></blockquote> 202 203<p> 204Much as using Boost.Flyweight reduces memory consumption due to the internal 205sharing of duplicate values, serializing <code>flyweight</code>s can also 206result in smaller archive files, as a common value is only stored 207once and their associated <code>flyweight</code>s get saved as references to it. 208This policy is observed even if <code>flyweight</code> underlying type is 209not <a href="../../../serialization/doc/traits.html#tracking">tracked</a> 210by Boost.Serialization. 211</p> 212 213<p> 214See <a href="../examples.html#example6">example 6</a> at the examples section 215for an illustration of use of Boost.Flyweight serialization capabilities. 216</p> 217 218<h3><a name="requirements">Flyweight requirements</a></h3> 219 220<p> 221For <code>flyweight<T></code> to be instantiable, <code>T</code> must 222be <a href="https://boost.org/sgi/stl/Assignable.html"><code>Assignable</code></a>, 223<a href="https://boost.org/sgi/stl/EqualityComparable.html"><code>Equality 224Comparable</code></a> and must interoperate with 225<a href="../../../functional/hash/index.html">Boost.Hash</a>. 226The first requirement is probably met without any extra effort by the user, 227not so the other two, except for the most common basic types of C++ 228and the standard library. Equality and hashing of <code>T</code> are used 229internally by <code>flyweight<T></code> internal factory to maintain the 230common repository of unique <code>T</code> values referred to by the flyweight 231objects. Consult the Boost.Hash documentation 232<a href="../../../../doc/html/hash/custom.html">section</a> on extending 233that library for custom data types. 234</p> 235 236<p> 237As we have seen, equality and hash requirements on <code>T</code> are 238imposed by the particular type of <i>flyweight factory</i> internally used by 239<code>flyweight<T></code>. We will see later how the user can customize 240this factory to use equality and hash predicates other than the default, 241or even switch to an entirely different kind of factory which may impose 242another requirements on <code>T</code>, as described in the section on 243<a href="configuration.html">configuring Boost.Flyweight</a>. 244</p> 245 246<hr> 247 248<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.Flyweight tutorial" border="0"><br> 249Boost.Flyweight tutorial 250</a></div> 251<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.Flyweight tutorial" border="0"><br> 252Boost.Flyweight tutorial 253</a></div> 254<div class="next_link"><a href="key_value.html"><img src="../next.gif" alt="key-value flyweights" border="0"><br> 255Key-value flyweights 256</a></div><br clear="all" style="clear: all;"> 257 258<br> 259 260<p>Revised April 24th 2019</p> 261 262<p>© Copyright 2006-2019 Joaquín M López Muñoz. 263Distributed under the Boost Software 264License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> 265LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> 266http://www.boost.org/LICENSE_1_0.txt</a>) 267</p> 268 269</body> 270</html> 271