segmented_structure.cpp 4.3 KB

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