| Home | Libraries | People | FAQ | More

## Tutorial

### Basics

#### `boost::base_collection`

(Code samples from `basic_base.cpp`.)

Imagine we are developing a role playing game in C++ where sprites are rendered on screen; for the purposes of illustration we can model rendering simply as outputting some information to a `std::ostream`:

    struct sprite
    {
      sprite(int id):id{id}{}
      virtual ~sprite()=default;
      virtual void render(std::ostream& os)const=0;

      int id;
    };

The game features warriors, juggernauts (a special type of warrior) and goblins, each represented by its own class derived (directly or indirectly) from `sprite`:

    struct warrior:sprite
    {
      using sprite::sprite;
      warrior(std::string rank,int id):sprite{id},rank{std::move(rank)}{}

      void render(std::ostream& os)const override{os<<rank<<" "<<id;}

      std::string rank="warrior";
    };

    struct juggernaut:warrior
    {
      juggernaut(int id):warrior{"juggernaut",id}{}
    };

    struct goblin:sprite
    {
      using sprite::sprite;
      void render(std::ostream& os)const override{os<<"goblin "<<id;}
    };

Let us populate a polymorphic collection with an assortment of sprites:

    #include <boost/poly_collection/base_collection.hpp>
    ...

    boost::base_collection<sprite> c;

    std::mt19937                 gen{92748}; // some arbitrary random seed
    std::discrete_distribution<> rnd{{1,1,1}};
    for(int i=0;i<8;++i){        // assign each type with 1/3 probability
      switch(rnd(gen)){
        case 0: c.insert(warrior{i});break;
        case 1: c.insert(juggernaut{i});break;
        case 2: c.insert(goblin{i});break;
      }
    }

There are two aspects to notice here:

- `boost::base_collection` does not have a `push_back` member function like, say, `std::vector`, as the order in which elements are stored cannot be freely chosen by the user code —we will see more about this later. The insertion mechanisms are rather those of containers like `std::unordered_multiset`, namely `insert` and `emplace` with or without a position hint.
- Elements are not created with `new` but constructed on the stack and passed directly much like one would do with a standard non-polymorphic container.

| Important
Elements inserted into a `boost::base_collection` (or the other containers of Boost.PolyCollection) must be copyable and assignable; strictly speaking, they must at least model `MoveConstructible` and either be `MoveAssignable` or not throw on move construction. This might force you to revisit your code as it is customary to explicitly forbid copying at the base level of a virtual hierarchy to avoid slicing.

Rendering can now be implemented with a simple `for` loop over `c`:

    const char* comma="";
    for(const sprite& s:c){
      std::cout<<comma;
      s.render(std::cout);
      comma=",";
    }
    std::cout<<"\n";

The output being:

    juggernaut 0,juggernaut 4,juggernaut 7,goblin 1,goblin 3,goblin 5,warrior 2,warrior 6

As we have forewarned, the traversal order does not correspond to that of insertion. Instead, the elements are grouped in segments according to their concrete type. Here we see that juggernauts come first, followed by goblins and warriors. In general, no assumptions should be made about segment ordering, which may be different for this very example in your environment. On the other hand, elements inserted into an already existing segment always come at the end (except if a hint is provided). For instance, after inserting a latecomer goblin with `id==8`:

    c.insert(goblin{8});

the rendering loop outputs (new element in red):

    juggernaut 0,juggernaut 4,juggernaut 7,goblin 1,goblin 3,goblin 5,goblin 8,warrior 2,warrior 6

Deletion can be done in the usual way:

    // find element with id==7 and remove it
    auto it=std::find_if(c.begin(),c.end(),[](const sprite& s){return s.id==7;});
    c.erase(it);

Now rendering emits:

    juggernaut 0,juggernaut 4,goblin 1,goblin 3,goblin 5,goblin 8,warrior 2,warrior 6

#### `boost::function_collection`

(Code samples from `basic_function.cpp`. C++14 `std::make_unique` is used.)

Well into the development of the game, the product manager requests that two new types of entities be added to the rendering loop:

- Overlaid messages, such as scores, modelled as `std::string`s.
- Pop-up windows coming from a third party library that, unfortunately, do not derive from `sprite` and use their own `display` member functon for rendering:

    struct window
    {
      window(std::string caption):caption{std::move(caption)}{}

      void display(std::ostream& os)const{os<<"["<<caption<<"]";}

      std::string caption;
    };

We then decide to refactor the code so that sprites, messsages and windows are stored in dedicated containers:

    std::vector<std::unique_ptr<sprite>> sprs;
    std::vector<std::string>             msgs;
    std::vector<window>                  wnds;

and define our rendering container as a `boost::function_collection` of callable entities —function pointers or objects with a function call `operator()`— accepting a `std::ostream&` as a parameter

    #include <boost/poly_collection/function_collection.hpp>
    ...

    // function signature accepting std::ostream& and returning nothing
    using render_callback=void(std::ostream&);

    boost::function_collection<render_callback> c;

which we fill with suitable adaptors for `sprite`s, `std::string`s and `window`s, respectively. Lambda functions allow for a particularly terse code.

    auto render_sprite(const sprite& s){
      return [&](std::ostream& os){s.render(os);};
    }

    auto render_message(const std::string& m){
      return [&](std::ostream& os){os<<m;};
    }

    auto render_window(const window& w){
      return [&](std::ostream& os){w.display(os);};
    }
    ...

    for(const auto& ps:sprs)c.insert(render_sprite(*ps));
    for(const auto& m:msgs)c.insert(render_message(m));
    for(const auto& w:wnds)c.insert(render_window(w));

The rendering loop now looks like this:

    const char* comma="";
    for(const auto& cbk:c){
      std::cout<<comma;
      cbk(std::cout);
      comma=",";
    }
    std::cout<<"\n";

and produces the following for a particular scenario of sprites, messages and windows:

    juggernaut 0,goblin 1,warrior 2,goblin 3,"stamina: 10,000","game over",[pop-up 1],[pop-up 2]

The container we have just created works in many respects like a `std::vector<std::function<render_callback>>`, the main difference being that with `boost::function_collection` callable entities of the same type are packed together in memory [12], thus increasing performance (which is the whole point of using Boost.PolyCollection), while a vector of `std::function`s results in an individual allocation for each entity stored [13]. In fact, the `value_type` elements held by a `boost::function_collection` are actually not `std::function`s, although they behave analogously and can be converted to `std::function` if needed:

    auto cbk=*c.begin();
    cbk(std::cout); // renders first element to std::cout
    std::function<render_callback> f=cbk;
    f(std::cout);   // exactly the same

There is a reason for this: elements of a polymorphic collection cannot be freely assigned to by the user as this could end up trying to insert an object into a segment of a different type. So, unlike with `std::function`, this will not work:

    *c.begin()=render_message("last minute message"); // compile-time error

#### `boost::any_collection`

(Code samples from `basic_any.cpp`.)

| Note
Here we just touch on the bare essentials of Boost.TypeErasure needed to present `boost::any_collection`. The reader is advised to read Boost.TypeErasure documentation for further information.

After measuring the performance of the latest changes, we find that rendering is too slow and decide to refactor once again: if we could store all the entities --sprites, messages and windows-- into one single container, that would eliminate a level of indirection. The problem is that these types are totally unrelated to each other.

Boost.TypeErasure provides a class template `boost::type_erasure::any<Concept>` able to hold an object of whatever type as long as it conforms to the interface specified by `Concept`. In our case, we find it particularly easy to implement a common interface for rendering by providing overloads of `operator<<`

    std::ostream& operator<<(std::ostream& os,const sprite& s)
    {
      s.render(os);
      return os;
    }

    // std::string already has a suitable operator<<

    std::ostream& operator<<(std::ostream& os,const window& w)
    {
      w.display(os);
      return os;
    }

so that we can use it to specify the interface all entities have to adhere to:

    #include <boost/poly_collection/any_collection.hpp>
    #include <boost/type_erasure/operators.hpp>
    ...

    using renderable=boost::type_erasure::ostreamable<>;
    boost::any_collection<renderable> c;

The collection just created happily accepts insertion of heterogeneous entities (since interface conformity is silently checked at compile time)

    // populate with sprites
    std::mt19937                 gen{92748}; // some arbitrary random seed
    std::discrete_distribution<> rnd{{1,1,1}};
    for(int i=0;i<4;++i){        // assign each type with 1/3 probability
      switch(rnd(gen)){
        case 0: c.insert(warrior{i});break;
        case 1: c.insert(juggernaut{i});break;
        case 2: c.insert(goblin{i});break;
      }
    }

    // populate with messages
    c.insert(std::string{"\"stamina: 10,000\""});
    c.insert(std::string{"\"game over\""});

    // populate with windows
    c.insert(window{"pop-up 1"});
    c.insert(window{"pop-up 2"});

and rendering becomes

    const char* comma="";
    for(const auto& r:c){
      std::cout<<comma<<r;
      comma=",";
    }
    std::cout<<"\n";

with output

    [pop-up 1],[pop-up 2],juggernaut 0,goblin 1,goblin 3,warrior 2,"stamina: 10,000","game over"

As was the case with `boost::function_collection`, this container is similar to a `std::vector<boost::type_erasure::any<Concept>>` but has better performance due to packing of same-type elements. Also, the `value_type` of a `boost::any_collection<Concept>` is not `boost::type_erasure::any<Concept>`, but a similarly behaving entity [14]. In any case, we are not accessing sprites through an abstract `sprite&` anymore, so we could as well dismantle the virtual hierarchy and implement each type autonomously: this is left as an exercise to the reader.

### Deeper into the segmented nature of Boost.PolyCollection

(Code samples from `segmented_structure.cpp`. C++14 `std::make_unique` is used.)

#### Type registration

Getting back to our `boost::base_collection` example, suppose we want to refactor the populating code as follows:

    std::unique_ptr<sprite> make_sprite()
    {
      static std::mt19937                 gen{92748};
      static std::discrete_distribution<> rnd{{1,1,1}};
      static int                          id=0;

      switch(rnd(gen)){
        case 0: return std::make_unique<warrior>(id++);break;
        case 1: return std::make_unique<juggernaut>(id++);break;
        case 2: return std::make_unique<goblin>(id++);break;
      }
    }
    ...

    for(int i=0;i<8;++i)c.insert(*make_sprite());
    // throws boost::poly_collection::unregistered_type

Unexpectedly, this piece of code throws an exception of type `boost::poly_collection::unregistered_type`. What has changed from our original code?

Suppose a `warrior` has been created by `make_sprite`. The statement `c.insert(*make_sprite())` is passing the object as a `sprite&`: even though `boost::base_collection` is smart enough to know that the object is actually derived from `sprite` (by using `typeid()`) and slicing is to be avoided, there is no way that a segment for it can be created without accessing the type `warrior` at compile time for the proper internal class templates to be instantiated [15]. This did not happen in the pre-refactoring code because objects were passed as references to their true types.

A type is said to be registered into a polymorphic collection if there is a (potentially empty) segment created for it. This can be checked with:

    std::cout<<c.is_registered<warrior>()<<"\n";       // prints 0
    std::cout<<c.is_registered(typeid(warrior))<<"\n"; // alternate syntax

Registration happens automatically when the object is passed as a reference to its true type or `emplace`'d, and explicitly with `register_types`:

    c.register_types<warrior,juggernaut,goblin>();
    // everything works fine now
    for(int i=0;i<8;++i)c.insert(*make_sprite());

Once `T` has been registered into a polymorphic collection, it remains so regardless of whether objects of type `T` are stored or not, except if the collection is moved from, assigned to, or swapped.

As slicing is mainly an issue with OOP, `unregistered_type` exceptions are expected to be much less frequent with `boost::function_collection` and `boost::any_collection`. Contrived examples can be found, though:

    boost::any_collection<renderable> c1,c2;
    ... // populate c2

    c1.insert(*c2.begin()); // throws: actual type of *c2.begin() not known by c1

#### Segment-specific interface

For most of the interface of a polymorphic collection, it is possible to only refer to the elements of a given segment by providing either their type or `typeid()`. For instance:

    ... // populate c with 8 assorted entities

    std::cout<<c.size()<<"\n";                    // 8 sprites
    std::cout<<c.size<juggernaut>()<<"\n";        // 2 juggernauts
    std::cout<<c.size(typeid(juggernaut))<<"\n";  // alternate syntax
    c.clear<juggernaut>();                        // remove juggenauts only
    std::cout<<c.empty<juggernaut>()<<"\n";       // 1 (no juggernauts left)
    std::cout<<c.size()<<"\n";                    // 6 sprites remaining

Note that any of these (except `reserve`) will throw `boost::poly_collection::unregistered_type` if the type is not registered. Segment-specific addressability also includes traversal:

#### Local iterators

The following runs only over the `warrior`s of the collection:

    const char* comma="";
    for(auto first=c.begin(typeid(warrior)),last=c.end(typeid(warrior));
        first!=last;++first){
      std::cout<<comma;
      first->render(std::cout);
      comma=",";
    }
    std::cout<<"\n";

Output:

    warrior 2,warrior 6

`begin|end(typeid(T))` return objects of type `local_base_iterator` associated to the segment for `T`. These iterators dereference to the same value as regular iterators (in the case of `boost::base_collection<base>`, `base&`) but can only be used to traverse a given segment (for instance, `local_base_iterator`'s from different segments cannot be compared between them). In exchange, `local_base_iterator` is a `RandomAccessIterator`, whereas whole-collection iterators only model `ForwardIterator`.

A terser range-based `for` loop can be used with the convenience `segment` member function:

    const char* comma="";
    for(const auto& x:c.segment(typeid(warrior))){
      std::cout<<comma;
      x.render(std::cout);
      comma=",";
    }
    std::cout<<"\n";

Even more powerful than `local_base_iterator` is `local_iterator<T>`:

    const char* comma="";
    for(auto first=c.begin<warrior>(),last=c.end<warrior>();
        first!=last;++first){
      first->rank.insert(0,"super");
      std::cout<<comma;
      first->render(std::cout);
      comma=",";
    }
    std::cout<<"\n";

    // range-based for loop alternative

    const char* comma="";
    for(auto& x:c.segment<warrior>()){
      x.rank.insert(0,"super");
      std::cout<<comma;
      x.render(std::cout);
      comma=",";
    }
    std::cout<<"\n";

This appends a `"super"` prefix to the `rank` data member of existing warriors:

    superwarrior 2,superwarrior 6

The observant reader will have noticed that in order to access `rank`, which is a member of `warrior` rather than its base class `sprite`, `first` (or `x` in the range `for` loop version) has to refer to a `warrior&`, and this is precisely the difference between `local_iterator<warrior>` (the type returned by `begin<warrior>()`) and `local_base_iterator`. `local_iterator<warrior>` is also a `RandomAccessIterator`: for most respects, [`begin<T>()`, `end<T>()`) can be regarded as a range over an array of `T` objects. `local_iterator<T>`s can be explicitly converted to `local_base_iterator`s. Conversely, if a `local_base_iterator` is associated to a segment for `T`, it can then be explictly converted to a `local_iterator<T>` (otherwise the conversion is undefined behavior).

The figure shows the action scopes of all the iterators associated to a polymorphic collection (`const_` versions not included):

We have yet to describe the bottom part of the diagram. Whereas `segment(typeid(T))` is used to range over the elements of a particular segment, `segment_traversal()` returns an object for ranging over segments, so that the whole collection can be processed with a nested segment-element `for` loop like the following:

    const char* comma="";
    for(auto seg:c.segment_traversal()){
      for(sprite& s:seg){
        std::cout<<comma;
        s.render(std::cout);
        comma=",";
      }
    }
    std::cout<<"\n";

Segment decomposition of traversal loops forms the basis of improved-performance algorithms.

#### Reserve

Much like `std::vector`, segments can be made to reserve memory in advance to minimize reallocations:

    c.reserve<goblin>(100); // no reallocation till we exceed 100 goblins
    std::cout<<c.capacity<goblin>()<<"\n"; // prints 100

If there is no segment for the indicated type (here, `goblin`), one is automatically created. This is in contrast with the rest of segment-specific member functions, which throw `boost::poly_collection::unregistered_type`.

`reserve` can deal with all segments at once. The following

    c.reserve(1000); // reserve(1000) for each segment
    std::cout<<c.capacity<warrior>()<<", "
             <<c.capacity<juggernaut>()<<", "
             <<c.capacity<goblin>()<<"\n"; // prints 1000, 1000, 1000

instructs every existing segment to reserve 1,000 elements. If a segment is created later (through element insertion or with type registration), its capacity will be different.

| Note
Unlike standard containers, collection-level `capacity()` and `max_size()` are not provided because their usual semantics cannot be applied to Boost.PolyCollection: for instance, `capacity()` is typically used to check how many elements can be inserted without reallocation, but in a segmented structure that depends on the exact types of the elements and whether they are registered or not.

### Insertion and emplacement

(Code samples from `insertion_emplacement.cpp`.)

We already know that `insert(x)`, without further positional information, stores `x` at the end of its associated segment. When a regular iterator `it` is provided, insertion happens at the position indicated if both `it` and `x` belong in the same segment; otherwise, `it` is ignored. For instance, if our sprite collection has the following entities:

    juggernaut 0,juggernaut 4,juggernaut 7,goblin 1,goblin 3,goblin 5,warrior 2,warrior 6

then this code:

    c.insert(c.begin(),juggernaut{8});

puts the new `juggernaut` at the beginning:

    juggernaut 8,juggernaut 0,juggernaut 4,juggernaut 7,goblin 1,...

whereas the position hint at

    c.insert(c.begin(),goblin{9});

is ignored and the new `goblin` gets inserted at the end of its segment:

    juggernaut 8,...,juggernaut 7,goblin 1,goblin 3,goblin 5,goblin 9,warrior 2,...

Local iterators can also be used to indicate the insertion position:

    c.insert(c.begin<juggernaut>()+2,juggernaut{10});
                               // ^^ remember local iterators are random access

    juggernaut 8,juggernaut 0,juggernaut 10,juggernaut 4,juggernaut 7,goblin 1,...

There is a caveat, though: when using a local iterator, the element inserted must belong to the indicated segment:

    c.insert(c.begin(typeid(warrior)),juggernaut{11}); // undefined behavior!!

Member functions are provided for range insertion, with and without a position hint:

    boost::base_collection<sprite> c2;

    c2.insert(c.begin(),c.end()); // read below

    // add some more warriors
    std::array<warrior,3> aw={{11,12,13}};
    c2.insert(aw.begin(),aw.end());

    // add some goblins at the beginning of their segment
    std::array<goblin,3> ag={{14,15,16}};
    c2.insert(c2.begin<goblin>(),ag.begin(),ag.end());

As already explained, care must be taken that types be pre-registered into the collection if they are not passed as references to their actual type. So, why did not this line

    c2.insert(c.begin(),c.end());

throw `boost::poly_collection::unregistered_type`? As it happens, in the special case where the inserted range belongs to a polymorphic collection of the same type, registration is done automatically [16].

Emplacement is slightly different for Boost.PolyCollection than with standard containers. Consider this attempt at emplacing a `goblin`:

    c.emplace(11); // does not compile

If examined carefully, it is only natural that the code above not compile: Boost.PolyCollection cannot possibly know that it is precisely a `goblin` that we want to emplace and not some other type constructible from an `int` (like `warrior`, `juggernaut` or an unrelated class). So, the type of the emplaced element has to be specified explicitly:

    c.emplace<goblin>(11); // now it works

As with `insert`, a position can be indicated for emplacing:

    c.emplace_hint<juggernaut>(c.begin(),12); // at the beginning if possible
    c.emplace_pos<goblin>(c.begin<goblin>()+2,13); // amidst the goblins
    c.emplace_pos<warrior>(c.begin(typeid(warrior)),14); // local_base_iterator

Note the naming here: `emplace_hint` is used when the position is indicated with a regular iterator, and for local iterators it is `emplace_pos`.

### Exceptions

(Code samples from `exceptions.cpp`.)

Besides the usual exceptions like `std::bad_alloc` and those generated by user-provided types, polymorphic collections can throw the following:

- `boost::poly_collection::unregistered_type`
- `boost::poly_collection::not_copy_constructible`
- `boost::poly_collection::not_equality_comparable`

The situations in which the first is raised have been already discussed; let us focus on the other two.

We have a new type of sprite in our game defined by the non-copyable class `elf`:

    struct elf:sprite
    {
      using sprite::sprite;
      elf(const elf&)=delete; // not copyable
      elf(elf&&)=default;     // but moveable
      void render(std::ostream& os)const override{os<<"elf "<<id;}
    };

and we use it without problems until we write this:

    c.insert(elf{0}); // no problem
    ...

    c2=c; // throws boost::poly_collection::not_copy_constructible

The first insertion works because the `elf` object passed is temporary and can be moved into the container, but the second statement actually needs to copy the `elf` elements in `c` to `c2`, hence the exception.

The potentially surprising aspect of this behavior is that standard containers signal this kind of problems by failing at compile time. Here we cannot afford this luxury because the exact types contained in a polymorphic collection are not known until run time (for instance, if `elf` elements had been erased before copying `c` to `c2` everything would have worked): basically, the deferral of errors from compile time to run time is an intrinsic feature of dynamic polymorphism.

In the same vein, equality comparison requires that elements themselves be equality comparable:

    c.clear<elf>(); // get rid of non-copyable elfs
    c2=c;           // now it works
    // check that the two are indeed equal
    std::cout<<(c==c2)<<"\n";
                    // throws boost::poly_collection::not_equality_comparable

The above is unremarkable once we notice we have not defined `operator==` for any `sprite`. The problem may go unnoticed for quite some time, however, because determining that two polymorphic collections are equal (i.e. all their non-empty segments are equal) can return `false` without comparing anything at all (for instance, if segment sizes differ), in which case no exception is thrown.

| Note
Operators for `<`, `<=`, `>` and `>=` comparison are not provided because segment order is not fixed and may vary across otherwise identical collections. The situation is similar to that of standard unordered associative containers.

These three are all the intrinsic exceptions thrown by Boost.PolyCollection. The implication is that if a type is `CopyConstructible`, `MoveAssignable` (or move construction does not throw) and `EqualityComparable`, then the entire interface of Boost.PolyCollection is unrestrictedly available for it [17].

### Algorithms

(Code samples from `algorithms.cpp`. C++14 generic lambda expressions are used.)

The ultimate purpose of Boost.PolyCollection is to speed up the processing of large quantities of polymorphic entities, in particular for those operations that involve linear traversal as implemented with a `for`-loop or using the quintessential `std::for_each` algorithm.

    const char* comma="";
    std::for_each(c.begin(),c.end(),[&](const sprite& s){
      std::cout<<comma;
      s.render(std::cout);
      comma=",";
    });
    std::cout<<"\n";

Replacing the container used in the program from classic alternatives to Boost.PolyCollection:

- `std::vector<base*>` (or similar) → `boost::base_collection<base>`
- `std::vector<std::function<signature>>` → `boost::function_collection<signature>`
- `std::vector<boost::type_erasure::any<concept_>>` → `boost::any_collection<concept_>`

is expected to increase performance due to better caching and branch prediction behavior. But there is still room for improvement.

Consider this transformation of the code above using a double segment-element loop (based on the local iterator capabilities of Boost.PolyCollection):

    const char* comma="";
    for(auto seg_info:c.segment_traversal()){
      for(const sprite& s:seg_info){
        std::cout<<comma;
        s.render(std::cout);
        comma=",";
      }
    }
    std::cout<<"\n";

Although not obvious at first sight, this version of the same basic operation is actually faster than the first one: for a segmented structure such as used by Boost.PolyCollection, each iteration with the non-local iterator passed to `std::for_each` involves:

1. hopping to next position in the segment,
2. checking for end of segment (always),
3. if at end (infrequent), selecting the next segment,
4. checking for end of range (always),

whereas in the second version, iteration on the inner loop, where most processing happens, is a simple increment-and-check operation, that is, there is one less check (which happens at the much shorter outer loop). When the workload of the algorithm (the actually useful stuff done with the elements themselves) is relatively light, the overhead of looping can be very significant.

To make it easier for the user to take advantage of faster segment-element looping, Boost.PolyCollection provides its own version of `for_each` based on that technique:

    #include <boost/poly_collection/algorithm.hpp>
    ...

    const char* comma="";
    boost::poly_collection::for_each(c.begin(),c.end(),[&](const sprite& s){
      std::cout<<comma;
      s.render(std::cout);
      comma=",";
    });
    std::cout<<"\n";

`boost::poly_collection::for_each` has the same interface and behavior as `std::for_each` except for the fact that it only works for (non-local) iterators of a polymorphic container [18]. Versions of other standard algorithms are provided as well:

    auto n=boost::poly_collection::count_if(
      c.begin(),c.end(),[](const sprite& s){return s.id%2==0;});
    std::cout<<n<<" sprites with even id\n";

In fact, variants are given of most (though not all) of the algorithms in `<algorithm>` among those that are compatible with polymorphic collections [19]. Check the reference for details.

#### Type restitution

By type restitution we mean the generic process of getting a concrete entity from an abstract one by providing missing type information:

    sprite*  ps=new warrior{5};
    // sprite -> warrior
    warrior* pw=static_cast<warrior*>(ps);

    boost::type_erasure::any<renderable> r=std::string{"hello"};
    // renderable -> std::string
    std::string& str=boost::type_erasure::any_cast<std::string&>(r);

Type restitution has the potential to increase performance. Consider for instance the following:

    // render r with std::string restitution
    if(boost::type_erasure::typeid_of(r)==typeid(std::string)){
      std::string& str=boost::type_erasure::any_cast<std::string&>(r);
      std::cout<<str<<"\n";
    }
    else{
      std::cout<<r<<"\n";
    }

Behaviorwise this code is equivalent to simply executing `std::cout<<r<<"\n"`, but when type restitution succeeds the statement `std::cout<<str<<"\n"` is skipping a virtual-like call that would have happened if `r` were used instead. From a general point of view, supplying the compiler with extra type information allows it to perform more optimizations than in the abstract case, inlining being the prime example.

All Boost.PolyCollection algorithms accept an optional list of types for restitution. Let us use the `boost::any_collection` scenario to illustrate this point:

    const char* comma="";
    boost::poly_collection::for_each
      <warrior,juggernaut,goblin>( // restituted types
      c.begin(),c.end(),[&](const auto& x){ // loop traverses *all* elements
        std::cout<<comma<<x;
        comma=",";
      });
    std::cout<<"\n";

Output:

    warrior 2,warrior 6,[pop-up 1],[pop-up 2],juggernaut 0,juggernaut 4,
    juggernaut 7,goblin 1,goblin 3,goblin 5,"stamina: 10,000","game over"

This rendering loop differs from the non-restituting one in two aspects:

- A list of types is provided as template arguments to the algorithm. This is an indication that the types may be actually present in the collection, not a promise. Also, the list of types need not be exhaustive, that is, some unlisted types could be present in the collection —in the example above, the loop traverses all elements (including `std::string`s and `window`s), not only those corresponding to restituted types. In general, the more types are restituted, the greater the potential improvement in performance.
- The lambda function passed is a generic one accepting its argument as `const auto&` [20].

Internally, `boost::poly_collection::for_each` checks for each segment if its type, say `T`, belongs in the type restitution list: if this is the case, the lambda function is passed a `const T&` rather than the generic `const boost::any_collection::value_type&`. For each restituted type we are saving indirection calls and possibly getting inlining optimizations, etc. As we see in the performance section, the speedup can be very significant.

Type restitution works equally for the rest of collections of Boost.PolyCollection. When using `boost::base_collection`, though, the case of improved performance is more tricky:

    const char* comma="";
    boost::poly_collection::for_each<warrior,juggernaut,goblin>(
      c.begin(),c.end(),[&](const auto& s){
        std::cout<<comma;
        s.render(std::cout);
        comma=",";
      });
    std::cout<<"\n";

The problem here is that, even though the argument to the lambda function will be restituted (when appropriate) to `warrior&`, `juggernaut&` or `goblin&`, using it still involves doing a virtual function call in `s.render(std::cout)`. Whether this call is resolved to a non-virtual one depends on the quality of implementation of the compiler:

- If the concrete class is marked as `final`, the compiler in principle has enough information to get rid of the virtual function call.
- Other than this, devirtualization capabilities may be able to figure out that the type restitution scenario is actually casting the element to its true type, in which case, again, virtual calls are not needed.

[12] Note that all `sprite`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.

[13] Except when small buffer optimization applies.

[14] Actually, it is `boost::type_erasure::any<Concept2,boost::type_erasure::_self&>` for some internally defined `Concept2` that extends `Concept`.

[15] If this is conceptually difficult to grasp, consider the potentially more obvious case where `warrior` is defined in a dynamic module linked to the main program: the code of `boost::base_collection`, which has been compiled 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.

[16] That is, Boost.PolyCollection has enough static information to do type registration without further assistance from the user.

[17] Provided, of course, that the type has the right to be in the collection, that is, it is derived from the specified base, or callable with the specified signature, etc.

[18] For any other type of iterator, it is guaranteed not to compile.

[19] For example, algorithms requiring bidirectional iterators or a higher category are not provided because polymorphic collections have forward-only iterators.

[20] 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.