<p>
The container we have just created works in many respects like a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="identifier">render_callback</span><span class="special">>></span></code>,
the main difference being that with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_collection</span></code>
- callable entities of the same type are packed together in memory <a href="#ftn.poly_collection.tutorial.basics.boost_function_collection.f0" class="footnote" name="poly_collection.tutorial.basics.boost_function_collection.f0"><sup class="footnote">[10]</sup></a>, thus increasing performance (which is the whole point of using
+ callable entities of the same type are packed together in memory <a href="#ftn.poly_collection.tutorial.basics.boost_function_collection.f0" class="footnote" name="poly_collection.tutorial.basics.boost_function_collection.f0"><sup class="footnote">[12]</sup></a>, thus increasing performance (which is the whole point of using
Boost.PolyCollection), while a vector of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code>s
- results in an individual allocation for each entity stored <a href="#ftn.poly_collection.tutorial.basics.boost_function_collection.f1" class="footnote" name="poly_collection.tutorial.basics.boost_function_collection.f1"><sup class="footnote">[11]</sup></a>. In fact, the <code class="computeroutput"><span class="identifier">value_type</span></code>
+ results in an individual allocation for each entity stored <a href="#ftn.poly_collection.tutorial.basics.boost_function_collection.f1" class="footnote" name="poly_collection.tutorial.basics.boost_function_collection.f1"><sup class="footnote">[13]</sup></a>. In fact, the <code class="computeroutput"><span class="identifier">value_type</span></code>
elements held by a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">function_collection</span></code>
are actually <span class="emphasis"><em>not</em></span> <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code>s,
although they behave analogously and can be converted to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span></code> if needed:
this container is similar to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">type_erasure</span><span class="special">::</span><span class="identifier">any</span><span class="special"><</span><span class="identifier">Concept</span><span class="special">>></span></code> but has better performance due
to packing of same-type elements. Also, the <code class="computeroutput"><span class="identifier">value_type</span></code>
of a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">any_collection</span><span class="special"><</span><span class="identifier">Concept</span><span class="special">></span></code>
- is <span class="emphasis"><em>not</em></span> <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">type_erasure</span><span class="special">::</span><span class="identifier">any</span><span class="special"><</span><span class="identifier">Concept</span><span class="special">></span></code>, but a similarly behaving entity <a href="#ftn.poly_collection.tutorial.basics.boost_any_collection.f0" class="footnote" name="poly_collection.tutorial.basics.boost_any_collection.f0"><sup class="footnote">[12]</sup></a>. In any case, we are not accessing sprites through an abstract
+ is <span class="emphasis"><em>not</em></span> <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">type_erasure</span><span class="special">::</span><span class="identifier">any</span><span class="special"><</span><span class="identifier">Concept</span><span class="special">></span></code>, but a similarly behaving entity <a href="#ftn.poly_collection.tutorial.basics.boost_any_collection.f0" class="footnote" name="poly_collection.tutorial.basics.boost_any_collection.f0"><sup class="footnote">[14]</sup></a>. In any case, we are not accessing sprites through an abstract
<code class="computeroutput"><span class="identifier">sprite</span><span class="special">&</span></code>
anymore, so we could as well dismantle the virtual hierarchy and implement
each type autonomously: this is left as an exercise to the reader.
is to be avoided, there is no way that a segment for it can be created
without accessing the type <code class="computeroutput"><span class="identifier">warrior</span></code>
<span class="emphasis"><em>at compile time</em></span> for the proper internal class templates
- to be instantiated <a href="#ftn.poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="footnote" name="poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0"><sup class="footnote">[13]</sup></a>. This did not happen in the pre-refactoring code because objects
+ to be instantiated <a href="#ftn.poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="footnote" name="poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0"><sup class="footnote">[15]</sup></a>. This did not happen in the pre-refactoring code because objects
were passed as references to their true types.
</p>
<p>
<p>
throw <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">poly_collection</span><span class="special">::</span><span class="identifier">unregistered_type</span></code>? As it happens, in the
special case where the inserted range belongs to a polymorphic collection
- of the same type, registration is done automatically <a href="#ftn.poly_collection.tutorial.insertion_and_emplacement.f0" class="footnote" name="poly_collection.tutorial.insertion_and_emplacement.f0"><sup class="footnote">[14]</sup></a>.
+ of the same type, registration is done automatically <a href="#ftn.poly_collection.tutorial.insertion_and_emplacement.f0" class="footnote" name="poly_collection.tutorial.insertion_and_emplacement.f0"><sup class="footnote">[16]</sup></a>.
</p>
<p>
<a name="poly_collection.tutorial.insertion_and_emplacement.emplacement"></a>Emplacement
<a href="http://en.cppreference.com/w/cpp/named_req/MoveAssignable" target="_top"><span class="bold"><strong><code class="computeroutput"><span class="identifier">MoveAssignable</span></code></strong></span></a>
(or move construction does not throw) and <a href="http://en.cppreference.com/w/cpp/named_req/EqualityComparable" target="_top"><span class="bold"><strong><code class="computeroutput"><span class="identifier">EqualityComparable</span></code></strong></span></a>,
then the entire interface of Boost.PolyCollection is unrestrictedly available
- for it <a href="#ftn.poly_collection.tutorial.exceptions.f0" class="footnote" name="poly_collection.tutorial.exceptions.f0"><sup class="footnote">[15]</sup></a>.
+ for it <a href="#ftn.poly_collection.tutorial.exceptions.f0" class="footnote" name="poly_collection.tutorial.exceptions.f0"><sup class="footnote">[17]</sup></a>.
</p>
</div>
<div class="section">
<p>
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">poly_collection</span><span class="special">::</span><span class="identifier">for_each</span></code> has the same interface and behavior
as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></code> except for the fact that it only
- works for (non-local) iterators of a polymorphic container <a href="#ftn.poly_collection.tutorial.algorithms.f0" class="footnote" name="poly_collection.tutorial.algorithms.f0"><sup class="footnote">[16]</sup></a>. Versions of other standard algorithms are provided as well:
+ works for (non-local) iterators of a polymorphic container <a href="#ftn.poly_collection.tutorial.algorithms.f0" class="footnote" name="poly_collection.tutorial.algorithms.f0"><sup class="footnote">[18]</sup></a>. Versions of other standard algorithms are provided as well:
</p>
<pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">n</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">poly_collection</span><span class="special">::</span><span class="identifier">count_if</span><span class="special">(</span>
<span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),[](</span><span class="keyword">const</span> <span class="identifier">sprite</span><span class="special">&</span> <span class="identifier">s</span><span class="special">){</span><span class="keyword">return</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">id</span><span class="special">%</span><span class="number">2</span><span class="special">==</span><span class="number">0</span><span class="special">;});</span>
<p>
In fact, variants are given of most (though not all) of the algorithms in
<a href="http://en.cppreference.com/w/cpp/algorithm" target="_top"><code class="computeroutput"><span class="special"><</span><span class="identifier">algorithm</span><span class="special">></span></code></a>
- among those that are compatible with polymorphic collections <a href="#ftn.poly_collection.tutorial.algorithms.f1" class="footnote" name="poly_collection.tutorial.algorithms.f1"><sup class="footnote">[17]</sup></a>. Check the <a class="link" href="reference.html#poly_collection.reference.header_boost_poly_collection_alg" title='Header "boost/poly_collection/algorithm.hpp" synopsis'>reference</a>
+ among those that are compatible with polymorphic collections <a href="#ftn.poly_collection.tutorial.algorithms.f1" class="footnote" name="poly_collection.tutorial.algorithms.f1"><sup class="footnote">[19]</sup></a>. Check the <a class="link" href="reference.html#poly_collection.reference.header_boost_poly_collection_alg" title='Header "boost/poly_collection/algorithm.hpp" synopsis'>reference</a>
for details.
</p>
<div class="section">
</li>
<li class="listitem">
The lambda function passed is a generic one accepting its argument
- as <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">auto</span><span class="special">&</span></code> <a href="#ftn.poly_collection.tutorial.algorithms.type_restitution.f0" class="footnote" name="poly_collection.tutorial.algorithms.type_restitution.f0"><sup class="footnote">[18]</sup></a>.
+ as <code class="computeroutput"><span class="keyword">const</span> <span class="keyword">auto</span><span class="special">&</span></code> <a href="#ftn.poly_collection.tutorial.algorithms.type_restitution.f0" class="footnote" name="poly_collection.tutorial.algorithms.type_restitution.f0"><sup class="footnote">[20]</sup></a>.
</li>
</ul></div>
<p>
</div>
<div class="footnotes">
<br><hr style="width:100; text-align:left;margin-left: 0">
-<div id="ftn.poly_collection.tutorial.basics.boost_function_collection.f0" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_function_collection.f0" class="para"><sup class="para">[10] </sup></a>
+<div id="ftn.poly_collection.tutorial.basics.boost_function_collection.f0" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_function_collection.f0" class="para"><sup class="para">[12] </sup></a>
Note that all <code class="computeroutput"><span class="identifier">sprite</span></code>s
come into one segment: this is why goblins #1 and #3 are not adjacent.
Exercise for the reader: change the code of the example so that sprites
are further segmented according to their concrete type.
</p></div>
-<div id="ftn.poly_collection.tutorial.basics.boost_function_collection.f1" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_function_collection.f1" class="para"><sup class="para">[11] </sup></a>
+<div id="ftn.poly_collection.tutorial.basics.boost_function_collection.f1" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_function_collection.f1" class="para"><sup class="para">[13] </sup></a>
Except when small buffer optimization applies.
</p></div>
-<div id="ftn.poly_collection.tutorial.basics.boost_any_collection.f0" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_any_collection.f0" class="para"><sup class="para">[12] </sup></a>
+<div id="ftn.poly_collection.tutorial.basics.boost_any_collection.f0" class="footnote"><p><a href="#poly_collection.tutorial.basics.boost_any_collection.f0" class="para"><sup class="para">[14] </sup></a>
Actually, it is <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">type_erasure</span><span class="special">::</span><span class="identifier">any</span><span class="special"><</span><span class="identifier">Concept2</span><span class="special">,</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">type_erasure</span><span class="special">::</span><span class="identifier">_self</span><span class="special">&></span></code> for some internally defined
<code class="computeroutput"><span class="identifier">Concept2</span></code> that extends
<code class="computeroutput"><span class="identifier">Concept</span></code>.
</p></div>
-<div id="ftn.poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="footnote"><p><a href="#poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="para"><sup class="para">[13] </sup></a>
+<div id="ftn.poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="footnote"><p><a href="#poly_collection.tutorial.deeper_into_the_segmented_nature.type_registration.f0" class="para"><sup class="para">[15] </sup></a>
If this is conceptually difficult to grasp, consider the potentially
more obvious case where <code class="computeroutput"><span class="identifier">warrior</span></code>
is defined in a dynamic module linked to the main program: the code of
before linking, cannot even know the size of this as-of-yet unseen class,
so hardly can it allocate a segment for the received object.
</p></div>
-<div id="ftn.poly_collection.tutorial.insertion_and_emplacement.f0" class="footnote"><p><a href="#poly_collection.tutorial.insertion_and_emplacement.f0" class="para"><sup class="para">[14] </sup></a>
+<div id="ftn.poly_collection.tutorial.insertion_and_emplacement.f0" class="footnote"><p><a href="#poly_collection.tutorial.insertion_and_emplacement.f0" class="para"><sup class="para">[16] </sup></a>
That is, Boost.PolyCollection has enough static information to do type
registration without further assistance from the user.
</p></div>
-<div id="ftn.poly_collection.tutorial.exceptions.f0" class="footnote"><p><a href="#poly_collection.tutorial.exceptions.f0" class="para"><sup class="para">[15] </sup></a>
+<div id="ftn.poly_collection.tutorial.exceptions.f0" class="footnote"><p><a href="#poly_collection.tutorial.exceptions.f0" class="para"><sup class="para">[17] </sup></a>
Provided, of course, that the type has the <span class="emphasis"><em>right</em></span> to
be in the collection, that is, it is derived from the specified base, or
callable with the specified signature, etc.
</p></div>
-<div id="ftn.poly_collection.tutorial.algorithms.f0" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.f0" class="para"><sup class="para">[16] </sup></a>
+<div id="ftn.poly_collection.tutorial.algorithms.f0" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.f0" class="para"><sup class="para">[18] </sup></a>
For any other type of iterator, it is guaranteed not to compile.
</p></div>
-<div id="ftn.poly_collection.tutorial.algorithms.f1" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.f1" class="para"><sup class="para">[17] </sup></a>
+<div id="ftn.poly_collection.tutorial.algorithms.f1" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.f1" class="para"><sup class="para">[19] </sup></a>
For example, algorithms requiring bidirectional iterators or a higher category
are not provided because polymorphic collections have forward-only iterators.
</p></div>
-<div id="ftn.poly_collection.tutorial.algorithms.type_restitution.f0" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.type_restitution.f0" class="para"><sup class="para">[18] </sup></a>
+<div id="ftn.poly_collection.tutorial.algorithms.type_restitution.f0" class="footnote"><p><a href="#poly_collection.tutorial.algorithms.type_restitution.f0" class="para"><sup class="para">[20] </sup></a>
This requires C++14, but the same effect can be achieved in C++11
providing an equivalent, if more cumbersome, functor with a templatized
call operator.