• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2016-2017 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/poly_collection for library home page.
7  */
8 
9 /* segment-specific operations */
10 
11 #include <algorithm>
12 #include <boost/poly_collection/any_collection.hpp>
13 #include <boost/poly_collection/base_collection.hpp>
14 #include <boost/type_erasure/operators.hpp>
15 #include <memory>
16 #include <random>
17 #include "rolegame.hpp"
18 
operator <<(std::ostream & os,const sprite & s)19 std::ostream& operator<<(std::ostream& os,const sprite& s)
20 {
21   s.render(os);
22   return os;
23 }
24 
operator <<(std::ostream & os,const window & w)25 std::ostream& operator<<(std::ostream& os,const window& w)
26 {
27   w.display(os);
28   return os;
29 }
30 
main()31 int main()
32 {
33   boost::base_collection<sprite> c;
34 
35 //[segmented_structure_1
36 //=  std::unique_ptr<sprite> make_sprite()
37 //=  {
38 //<-
39   auto make_sprite=[]()->std::unique_ptr<sprite>{
40 //->
41     static std::mt19937                 gen{92748};
42     static std::discrete_distribution<> rnd{{1,1,1}};
43     static int                          id=0;
44 
45     switch(rnd(gen)){
46 //<-
47       default:
48 //->
49       case 0: return std::make_unique<warrior>(id++);break;
50       case 1: return std::make_unique<juggernaut>(id++);break;
51       case 2: return std::make_unique<goblin>(id++);break;
52     }
53 //<-
54   };
55 //->
56 //=  }
57 //=  ...
58 //=
59 //<-
60   try{
61 //->
62   for(int i=0;i<8;++i)c.insert(*make_sprite());
63   // throws boost::poly_collection::unregistered_type
64 //<-
65   }catch(boost::poly_collection::unregistered_type&){}
66 //->
67 //]
68 
69 //[segmented_structure_2
70   std::cout<<c.is_registered<warrior>()<<"\n";       // prints 0
71   std::cout<<c.is_registered(typeid(warrior))<<"\n"; // alternate syntax
72 //]
73 
74 //[segmented_structure_3
75   c.register_types<warrior,juggernaut,goblin>();
76   // everything works fine now
77   for(int i=0;i<8;++i)c.insert(*make_sprite());
78 //]
79 
80   using renderable=boost::type_erasure::ostreamable<>;
81 //[segmented_structure_4
82   boost::any_collection<renderable> c1,c2;
83 //=  ... // populate c2
84 //=
85 //<-
86   c2.insert(window{"pop-up"});
87   try{
88 //->
89   c1.insert(*c2.begin()); // throws: actual type of *c2.begin() not known by c1
90 //<-
91   }catch(boost::poly_collection::unregistered_type&){}
92 //->
93 //]
94 
95 //[segmented_structure_5
96 //=  ... // populate c with 8 assorted entities
97 //=
98   std::cout<<c.size()<<"\n";                    // 8 sprites
99   std::cout<<c.size<juggernaut>()<<"\n";        // 2 juggernauts
100   std::cout<<c.size(typeid(juggernaut))<<"\n";  // alternate syntax
101   c.clear<juggernaut>();                        // remove juggenauts only
102   std::cout<<c.empty<juggernaut>()<<"\n";       // 1 (no juggernauts left)
103   std::cout<<c.size()<<"\n";                    // 6 sprites remaining
104 //]
105 
106 //[segmented_structure_6
107   const char* comma="";
108   for(auto first=c.begin(typeid(warrior)),last=c.end(typeid(warrior));
109       first!=last;++first){
110     std::cout<<comma;
111     first->render(std::cout);
112     comma=",";
113   }
114   std::cout<<"\n";
115 //]
116 
117 //[segmented_structure_7
118   /*=const char**/ comma="";
119   for(const auto& x:c.segment(typeid(warrior))){
120     std::cout<<comma;
121     x.render(std::cout);
122     comma=",";
123   }
124   std::cout<<"\n";
125 //]
126 
127 //[segmented_structure_8
128   /*=const char**/ comma="";
129   for(auto first=c.begin<warrior>(),last=c.end<warrior>();
130       first!=last;++first){
131     first->rank.insert(0,"super");
132     std::cout<<comma;
133     first->render(std::cout);
134     comma=",";
135   }
136   std::cout<<"\n";
137 
138   // range-based for loop alternative
139 
140   /*=const char**/ comma="";
141   for(auto& x:c.segment<warrior>()){
142     x.rank.insert(0,"super");
143 //<-
144     auto it=x.rank.begin();
145     x.rank.erase(it,it+5); // undo previos op, 5==len("super");
146 //->
147     std::cout<<comma;
148     x.render(std::cout);
149     comma=",";
150   }
151   std::cout<<"\n";
152 
153 //]
154 
155   auto render=[&](){
156 //[segmented_structure_9
157   const char* comma="";
158   for(auto seg:c.segment_traversal()){
159     for(sprite& s:seg){
160       std::cout<<comma;
161       s.render(std::cout);
162       comma=",";
163     }
164   }
165   std::cout<<"\n";
166 //]
167   };
168   render();
169 
170 //[segmented_structure_10
171   c.reserve<goblin>(100); // no reallocation till we exceed 100 goblins
172   std::cout<<c.capacity<goblin>()<<"\n"; // prints 100
173 //]
174 
175 //[segmented_structure_11
176   c.reserve(1000); // reserve(1000) for each segment
177   std::cout<<c.capacity<warrior>()<<", "
178            <<c.capacity<juggernaut>()<<", "
179            <<c.capacity<goblin>()<<"\n"; // prints 1000, 1000, 1000
180 //]
181 }
182