summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/poly_collection/example
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/poly_collection/example')
-rw-r--r--src/boost/libs/poly_collection/example/Jamfile.v249
-rw-r--r--src/boost/libs/poly_collection/example/algorithms.cpp171
-rw-r--r--src/boost/libs/poly_collection/example/basic_any.cpp73
-rw-r--r--src/boost/libs/poly_collection/example/basic_base.cpp59
-rw-r--r--src/boost/libs/poly_collection/example/basic_function.cpp103
-rw-r--r--src/boost/libs/poly_collection/example/exceptions.cpp62
-rw-r--r--src/boost/libs/poly_collection/example/insertion_emplacement.cpp109
-rw-r--r--src/boost/libs/poly_collection/example/perf.cpp604
-rw-r--r--src/boost/libs/poly_collection/example/rolegame.hpp78
-rw-r--r--src/boost/libs/poly_collection/example/segmented_structure.cpp181
10 files changed, 1489 insertions, 0 deletions
diff --git a/src/boost/libs/poly_collection/example/Jamfile.v2 b/src/boost/libs/poly_collection/example/Jamfile.v2
new file mode 100644
index 00000000..9bd5760e
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/Jamfile.v2
@@ -0,0 +1,49 @@
+# Copyright 2016-2017 Joaquín M López Muñoz.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+# See http://www.boost.org/libs/poly_collection for library home page.
+
+project
+ : requirements
+ <include>$(BOOST_ROOT)
+ <cxxstd>11
+ ;
+
+exe algorithms
+ : algorithms.cpp
+ : <cxxstd>14
+ ;
+
+exe basic_any
+ : basic_any.cpp
+ ;
+
+exe basic_base
+ : basic_base.cpp
+ ;
+
+exe basic_function
+ : basic_function.cpp
+ : <cxxstd>14
+ ;
+
+exe exceptions
+ : exceptions.cpp
+ ;
+
+exe insertion_emplacement
+ : insertion_emplacement.cpp
+ ;
+
+exe perf
+ : perf.cpp
+ :
+ : release
+ ;
+
+exe segmented_structure
+ : segmented_structure.cpp
+ : <cxxstd>14
+ ;
diff --git a/src/boost/libs/poly_collection/example/algorithms.cpp b/src/boost/libs/poly_collection/example/algorithms.cpp
new file mode 100644
index 00000000..30a7e09e
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/algorithms.cpp
@@ -0,0 +1,171 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* Boost.PolyCollection algorithms */
+
+#include <algorithm>
+#include <boost/poly_collection/algorithm.hpp>
+#include <boost/poly_collection/any_collection.hpp>
+#include <boost/poly_collection/base_collection.hpp>
+#include <boost/type_erasure/any.hpp>
+#include <boost/type_erasure/any_cast.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/type_erasure/operators.hpp>
+#include <boost/type_erasure/typeid_of.hpp>
+#include <random>
+#include "rolegame.hpp"
+
+std::ostream& operator<<(std::ostream& os,const sprite& s)
+{
+ s.render(os);
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,const window& w)
+{
+ w.display(os);
+ return os;
+}
+
+int main()
+{
+ boost::base_collection<sprite> c;
+
+ // populate 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;
+ }
+ }
+
+ auto render1=[](const boost::base_collection<sprite>& c){
+//[algorithms_1
+ const char* comma="";
+ std::for_each(c.begin(),c.end(),[&](const sprite& s){
+ std::cout<<comma;
+ s.render(std::cout);
+ comma=",";
+ });
+ std::cout<<"\n";
+//]
+ };
+ render1(c);
+
+ auto render2=[](const boost::base_collection<sprite>& c){
+//[algorithms_2
+ 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";
+//]
+ };
+ render2(c);
+
+ auto render3=[](const boost::base_collection<sprite>& c){
+//[algorithms_3
+//= #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";
+//]
+ };
+ render3(c);
+
+//[algorithms_4
+ 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";
+//]
+
+ using renderable=boost::type_erasure::ostreamable<>;
+ using standalone_renderable=boost::mpl::vector<
+ renderable,
+ boost::type_erasure::copy_constructible<>,
+ boost::type_erasure::typeid_<>
+ >;
+
+ {
+//[algorithms_5
+ sprite* ps=new warrior{5};
+ // sprite -> warrior
+ warrior* pw=static_cast<warrior*>(ps);
+//<-
+ (void)pw;
+ delete ps;
+//->
+
+//<-
+ boost::type_erasure::any<standalone_renderable> r=std::string{"hello"};
+//->
+//= boost::type_erasure::any<renderable> r=std::string{"hello"};
+ // renderable -> std::string
+ std::string& str=boost::type_erasure::any_cast<std::string&>(r);
+//]
+
+//[algorithms_6
+ // 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";
+ }
+//]
+ }
+
+ auto& bc=c;
+ {
+ boost::any_collection<renderable> c;
+ c.insert(bc.begin<warrior>(),bc.end<warrior>());
+ c.insert(bc.begin<juggernaut>(),bc.end<juggernaut>());
+ c.insert(bc.begin<goblin>(),bc.end<goblin>());
+ c.insert(std::string{"\"stamina: 10,000\""});
+ c.insert(std::string{"\"game over\""});
+ c.insert(window{"pop-up 1"});
+ c.insert(window{"pop-up 2"});
+
+//[algorithms_7
+ 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";
+//]
+ }
+
+//[algorithms_8
+ 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";
+//]
+}
diff --git a/src/boost/libs/poly_collection/example/basic_any.cpp b/src/boost/libs/poly_collection/example/basic_any.cpp
new file mode 100644
index 00000000..e2c2dc99
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/basic_any.cpp
@@ -0,0 +1,73 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* basic usage of boost::any_collection */
+
+#include <boost/poly_collection/any_collection.hpp>
+#include <boost/type_erasure/operators.hpp>
+#include <random>
+#include "rolegame.hpp"
+
+//[basic_any_1
+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;
+}
+//]
+
+int main()
+{
+//[basic_any_2
+//= #include <boost/poly_collection/any_collection.hpp>
+//= #include <boost/type_erasure/operators.hpp>
+//= ...
+//=
+ using renderable=boost::type_erasure::ostreamable<>;
+ boost::any_collection<renderable> c;
+//]
+
+//[basic_any_3
+ // 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"});
+//]
+
+
+//[basic_any_4
+ const char* comma="";
+ for(const auto& r:c){
+ std::cout<<comma<<r;
+ comma=",";
+ }
+ std::cout<<"\n";
+//]
+}
diff --git a/src/boost/libs/poly_collection/example/basic_base.cpp b/src/boost/libs/poly_collection/example/basic_base.cpp
new file mode 100644
index 00000000..4f6f92f6
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/basic_base.cpp
@@ -0,0 +1,59 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* basic usage of boost::base_collection */
+
+#include <algorithm>
+#include <boost/poly_collection/base_collection.hpp>
+#include <random>
+#include "rolegame.hpp"
+
+int main()
+{
+//[basic_base_1
+//= #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;
+ }
+ }
+//]
+
+ auto render=[&](){
+//[basic_base_2
+ const char* comma="";
+ for(const sprite& s:c){
+ std::cout<<comma;
+ s.render(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+//]
+ };
+ render();
+
+//[basic_base_3
+ c.insert(goblin{8});
+//]
+ render();
+
+//[basic_base_4
+ // 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);
+//]
+ render();
+}
diff --git a/src/boost/libs/poly_collection/example/basic_function.cpp b/src/boost/libs/poly_collection/example/basic_function.cpp
new file mode 100644
index 00000000..5ee47601
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/basic_function.cpp
@@ -0,0 +1,103 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* basic usage of boost::function_collection */
+
+#include <boost/poly_collection/function_collection.hpp>
+#include <functional>
+#include <memory>
+#include <random>
+#include <vector>
+#include "rolegame.hpp"
+
+int main()
+{
+//[basic_function_1
+ std::vector<std::unique_ptr<sprite>> sprs;
+ std::vector<std::string> msgs;
+ std::vector<window> wnds;
+//]
+
+ // populate sprs
+ 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: sprs.push_back(std::make_unique<warrior>(i));;break;
+ case 1: sprs.push_back(std::make_unique<juggernaut>(i));break;
+ case 2: sprs.push_back(std::make_unique<goblin>(i));break;
+ }
+ }
+
+ // populate msgs
+ msgs.push_back("\"stamina: 10,000\"");
+ msgs.push_back("\"game over\"");
+
+ // populate wnds
+ wnds.emplace_back("pop-up 1");
+ wnds.emplace_back("pop-up 2");
+
+//[basic_function_2
+//= #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;
+//]
+
+//[basic_function_3
+//<-
+ auto render_sprite=[](const sprite& s){
+//->
+//= auto render_sprite(const sprite& s){
+ return [&](std::ostream& os){s.render(os);};
+ }/*<-*/;/*->*/
+
+//<-
+ auto render_message=[](const std::string& m){
+//->
+//= auto render_message(const std::string& m){
+ return [&](std::ostream& os){os<<m;};
+ }/*<-*/;/*->*/
+
+//<-
+ auto render_window=[](const window& w){
+//->
+//= 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));
+//]
+
+//[basic_function_4
+ const char* comma="";
+ for(const auto& cbk:c){
+ std::cout<<comma;
+ cbk(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+//]
+
+//[basic_function_5
+ 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
+//]
+
+//[basic_function_6
+//= *c.begin()=render_message("last minute message"); // compile-time error
+//]
+}
diff --git a/src/boost/libs/poly_collection/example/exceptions.cpp b/src/boost/libs/poly_collection/example/exceptions.cpp
new file mode 100644
index 00000000..d5e946dc
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/exceptions.cpp
@@ -0,0 +1,62 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* Boost.PolyCollection exceptions */
+
+#include <algorithm>
+#include <array>
+#include <boost/poly_collection/base_collection.hpp>
+#include <random>
+#include "rolegame.hpp"
+
+int main()
+{
+ boost::base_collection<sprite> c,c2;
+
+ // populate 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;
+ }
+ }
+
+ auto render=[](const boost::base_collection<sprite>& c){
+ const char* comma="";
+ for(const sprite& s:c){
+ std::cout<<comma;
+ s.render(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+ };
+ render(c);
+
+ try{
+//[exceptions_1
+ c.insert(elf{0}); // no problem
+//= ...
+//=
+ c2=c; // throws boost::poly_collection::not_copy_constructible
+//]
+ }catch(boost::poly_collection::not_copy_constructible&){}
+
+ try{
+//[exceptions_2
+ 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
+//]
+ }catch(boost::poly_collection::not_equality_comparable&){}
+}
diff --git a/src/boost/libs/poly_collection/example/insertion_emplacement.cpp b/src/boost/libs/poly_collection/example/insertion_emplacement.cpp
new file mode 100644
index 00000000..a7beafb8
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/insertion_emplacement.cpp
@@ -0,0 +1,109 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* examples of insertion and emplacement */
+
+#include <algorithm>
+#include <array>
+#include <boost/poly_collection/base_collection.hpp>
+#include <random>
+#include "rolegame.hpp"
+
+int main()
+{
+ boost::base_collection<sprite> c;
+
+ // populate 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;
+ }
+ }
+
+ auto render=[](const boost::base_collection<sprite>& c){
+ const char* comma="";
+ for(const sprite& s:c){
+ std::cout<<comma;
+ s.render(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+ };
+ render(c);
+
+//[insertion_emplacement_1]
+ c.insert(c.begin(),juggernaut{8});
+//]
+ render(c);
+
+//[insertion_emplacement_2]
+ c.insert(c.begin(),goblin{9});
+//]
+ render(c);
+
+//[insertion_emplacement_3]
+ c.insert(c.begin<juggernaut>()+2,juggernaut{10});
+ // ^^ remember local iterators are random access
+//]
+ render(c);
+
+//[insertion_emplacement_4]
+//= c.insert(c.begin(typeid(warrior)),juggernaut{11}); // undefined behavior!!
+//]
+
+//[insertion_emplacement_5]
+ boost::base_collection<sprite> c2;
+
+ c2.insert(c.begin(),c.end()); // read below
+//<-
+ render(c2);
+//->
+
+ // add some more warriors
+ std::array<warrior,3> aw={{11,12,13}};
+ c2.insert(aw.begin(),aw.end());
+//<-
+ render(c2);
+//->
+
+ // 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());
+//<-
+ render(c2);
+//->
+//]
+
+//[insertion_emplacement_6]
+//<-
+ // same as line at beginning of previous snippet
+//->
+ c2.insert(c.begin(),c.end());
+//]
+
+//[insertion_emplacement_7]
+//= c.emplace(11); // does not compile
+//]
+
+//[insertion_emplacement_8]
+ c.emplace<goblin>(11); // now it works
+//]
+ render(c);
+
+//[insertion_emplacement_9]
+ 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
+//]
+ render(c);
+}
diff --git a/src/boost/libs/poly_collection/example/perf.cpp b/src/boost/libs/poly_collection/example/perf.cpp
new file mode 100644
index 00000000..4d19a9f6
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/perf.cpp
@@ -0,0 +1,604 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* Boost.PolyCollection performance tests */
+
+#include <algorithm>
+#include <array>
+#include <chrono>
+#include <cmath>
+#include <numeric>
+
+std::chrono::high_resolution_clock::time_point measure_start,measure_pause;
+
+template<typename F>
+double measure(F f)
+{
+ using namespace std::chrono;
+
+ static const int num_trials=10;
+ static const milliseconds min_time_per_trial(200);
+ std::array<double,num_trials> trials;
+ volatile decltype(f()) res; /* to avoid optimizing f() away */
+
+ for(int i=0;i<num_trials;++i){
+ int runs=0;
+ high_resolution_clock::time_point t2;
+
+ measure_start=high_resolution_clock::now();
+ do{
+ res=f();
+ ++runs;
+ t2=high_resolution_clock::now();
+ }while(t2-measure_start<min_time_per_trial);
+ trials[i]=duration_cast<duration<double>>(t2-measure_start).count()/runs;
+ }
+ (void)res; /* var not used warn */
+
+ std::sort(trials.begin(),trials.end());
+ return std::accumulate(
+ trials.begin()+2,trials.end()-2,0.0)/(trials.size()-4);
+}
+
+template<typename F>
+double measure(unsigned int n,F f)
+{
+ double t=measure(f);
+ return (t/n)*10E9;
+}
+
+void pause_timing()
+{
+ measure_pause=std::chrono::high_resolution_clock::now();
+}
+
+void resume_timing()
+{
+ measure_start+=std::chrono::high_resolution_clock::now()-measure_pause;
+}
+
+#include <algorithm>
+#include <array>
+#include <boost/poly_collection/algorithm.hpp>
+#include <boost/poly_collection/any_collection.hpp>
+#include <boost/poly_collection/base_collection.hpp>
+#include <boost/poly_collection/function_collection.hpp>
+#include <boost/ptr_container/ptr_container.hpp>
+#include <boost/type_erasure/any.hpp>
+#include <boost/type_erasure/callable.hpp>
+#include <boost/type_erasure/builtin.hpp>
+#include <boost/type_erasure/operators.hpp>
+#include <boost/type_erasure/typeid_of.hpp>
+#include <functional>
+#include <random>
+#include <string>
+#include <utility>
+#include <vector>
+
+//[perf_base_types
+struct base
+{
+ virtual ~base()=default;
+ virtual int operator()(int)const=0;
+};
+
+struct derived1 final:base
+{
+ derived1(int n):n{n}{}
+ virtual int operator()(int)const{return n;}
+
+ int n;
+};
+
+struct derived2 final:base
+{
+ derived2(int n):n{n}{}
+ virtual int operator()(int x)const{return x*n;}
+
+ int unused,n;
+};
+
+struct derived3 final:base
+{
+ derived3(int n):n{n}{}
+ virtual int operator()(int x)const{return x*x*n;}
+
+ int unused,n;
+};
+//]
+
+//[perf_function_types
+struct concrete1
+{
+ concrete1(int n):n{n}{}
+ int operator()(int)const{return n;}
+
+ int n;
+};
+
+struct concrete2
+{
+ concrete2(int n):n{n}{}
+ int operator()(int x)const{return x*n;}
+
+ int unused,n;
+};
+
+struct concrete3
+{
+ concrete3(int n):n{n}{}
+ int operator()(int x)const{return x*x*n;}
+
+ int unused,n;
+};
+//]
+
+template<typename Base>
+struct ptr_vector:boost::ptr_vector<Base>
+{
+public:
+ template<typename T>
+ void insert(const T& x)
+ {
+ this->push_back(new T{x});
+ }
+
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Base>
+struct sorted_ptr_vector:ptr_vector<Base>
+{
+ void prepare_for_for_each()
+ {
+ std::sort(
+ this->c_array(),this->c_array()+this->size(),
+ [](Base* x,Base* y){return typeid(*x).before(typeid(*y));});
+ }
+};
+
+template<typename Base>
+struct shuffled_ptr_vector:ptr_vector<Base>
+{
+ void prepare_for_for_each()
+ {
+ std::shuffle(
+ this->c_array(),this->c_array()+this->size(),std::mt19937(1));
+ }
+};
+
+template<typename Base>
+struct base_collection:boost::base_collection<Base>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Base,typename... T>
+struct poly_for_each_base_collection:base_collection<Base>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
+ }
+};
+
+template<typename Signature>
+struct func_vector:std::vector<std::function<Signature>>
+{
+ template<typename T> void insert(const T& x)
+ {
+ this->push_back(x);
+ }
+
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Signature>
+struct sorted_func_vector:func_vector<Signature>
+{
+ void prepare_for_for_each()
+ {
+ using value_type=typename sorted_func_vector::value_type;
+ std::sort(
+ this->begin(),this->end(),[](const value_type& x,const value_type& y){
+ return x.target_type().before(y.target_type());
+ });
+ }
+};
+
+template<typename Signature>
+struct shuffled_func_vector:func_vector<Signature>
+{
+ void prepare_for_for_each()
+ {
+ std::shuffle(this->begin(),this->end(),std::mt19937(1));
+ }
+};
+
+template<typename Signature>
+struct func_collection:boost::function_collection<Signature>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Signature,typename... T>
+struct poly_for_each_func_collection:func_collection<Signature>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
+ }
+};
+
+template<typename Concept>
+struct any_vector:std::vector<boost::type_erasure::any<Concept>>
+{
+ template<typename T> void insert(const T& x)
+ {
+ this->push_back(x);
+ }
+
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Concept>
+struct sorted_any_vector:any_vector<Concept>
+{
+ void prepare_for_for_each()
+ {
+ using value_type=typename sorted_any_vector::value_type;
+ std::sort(
+ this->begin(),this->end(),[](const value_type& x,const value_type& y){
+ return typeid_of(x).before(typeid_of(y));
+ });
+ }
+};
+
+template<typename Concept>
+struct shuffled_any_vector:any_vector<Concept>
+{
+ void prepare_for_for_each()
+ {
+ std::shuffle(this->begin(),this->end(),std::mt19937(1));
+ }
+};
+
+template<typename Concept>
+struct any_collection:boost::any_collection<Concept>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ std::for_each(this->begin(),this->end(),f);
+ }
+
+ void prepare_for_for_each(){}
+};
+
+template<typename Concept,typename... T>
+struct poly_for_each_any_collection:any_collection<Concept>
+{
+ template<typename F>
+ void for_each(F f)
+ {
+ boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
+ }
+};
+
+#include <iostream>
+
+template<typename... Printables>
+void print(Printables... ps)
+{
+ const char* delim="";
+ using seq=int[1+sizeof...(ps)];
+ (void)seq{0,(std::cout<<delim<<ps,delim=";",0)...};
+ std::cout<<"\n";
+}
+
+template<typename T>
+struct label
+{
+ label(const char* str):str{str}{}
+ operator const char*()const{return str;}
+ const char* str;
+};
+
+template<typename... T>
+struct element_sequence{};
+
+template<
+ typename... Element,
+ typename Container
+>
+void container_fill(unsigned int n,element_sequence<Element...>,Container& c)
+{
+ auto m=n/sizeof...(Element);
+ for(unsigned int i=0;i!=m;++i){
+ using seq=int[sizeof...(Element)];
+ (void)seq{(c.insert(Element(i)),0)...};
+ }
+}
+
+struct insert_perf_functor
+{
+ template<
+ typename... Element,
+ typename Container
+ >
+ std::size_t operator()(
+ unsigned int n,element_sequence<Element...> elements,label<Container>)const
+ {
+ pause_timing();
+ std::size_t res=0;
+ {
+ Container c;
+ resume_timing();
+ container_fill(n,elements,c);
+ pause_timing();
+ res=c.size();
+ }
+ resume_timing();
+ return res;
+ }
+};
+
+template<
+ typename... Element,
+ typename Container
+>
+double insert_perf(
+ unsigned int n,element_sequence<Element...> elements,label<Container> label)
+{
+ return measure(n,std::bind(insert_perf_functor{},n,elements,label));
+}
+
+template<
+ typename... Element,
+ typename... Container
+>
+void insert_perf(
+ unsigned int n0,unsigned int n1,unsigned int dsav,
+ element_sequence<Element...> elements,label<Container>... labels)
+{
+ std::cout<<"insert:\n";
+ print("n",labels...);
+
+ for(unsigned int s=0,n=n0;
+ (n=(unsigned int)std::round(n0*std::pow(10.0,s/1000.0)))<=n1;
+ s+=dsav){
+ unsigned int m=(unsigned int)std::round(n/sizeof...(Element)),
+ nn=m*sizeof...(Element);
+ print(nn,insert_perf(nn,elements,labels)...);
+ }
+}
+
+struct for_each_perf_functor
+{
+ template<typename F,typename Container>
+ auto operator()(F f,Container& c)const->decltype(f.res)
+ {
+ c.for_each(std::ref(f));
+ return f.res;
+ }
+};
+
+template<
+ typename... Element,
+ typename F,
+ typename Container
+>
+double for_each_perf(
+ unsigned int n,
+ element_sequence<Element...> elements,F f,label<Container>)
+{
+ Container c;
+ container_fill(n,elements,c);
+ c.prepare_for_for_each();
+ return measure(n,std::bind(for_each_perf_functor{},f,std::ref(c)));
+}
+
+template<
+ typename... Element,
+ typename F,
+ typename... Container
+>
+void for_each_perf(
+ unsigned int n0,unsigned int n1,unsigned int dsav,
+ element_sequence<Element...> elements,F f,label<Container>... labels)
+{
+ std::cout<<"for_each:\n";
+ print("n",labels...);
+
+ for(unsigned int s=0,n=n0;
+ (n=(unsigned int)std::round(n0*std::pow(10.0,s/1000.0)))<=n1;
+ s+=dsav){
+ unsigned int m=(unsigned int)std::round(n/sizeof...(Element)),
+ nn=m*sizeof...(Element);
+ print(nn,for_each_perf(nn,elements,f,labels)...);
+ }
+}
+
+//[perf_for_each_callable
+struct for_each_callable
+{
+ for_each_callable():res{0}{}
+
+ template<typename T>
+ void operator()(T& x){
+ res+=x(2);
+ }
+
+ int res;
+};
+//]
+
+//[perf_for_each_incrementable
+struct for_each_incrementable
+{
+ for_each_incrementable():res{0}{}
+
+ template<typename T>
+ void operator()(T& x){
+ ++x;
+ ++res;
+ }
+
+ int res;
+};
+//]
+
+int main(int argc, char *argv[])
+{
+ using test=std::pair<std::string,bool&>;
+
+ bool all=false,
+ insert_base=false,
+ for_each_base=false,
+ insert_function=false,
+ for_each_function=false,
+ insert_any=false,
+ for_each_any=false;
+ std::array<test,7> tests={{
+ {"all",all},
+ {"insert_base",insert_base},
+ {"for_each_base",for_each_base},
+ {"insert_function",insert_function},
+ {"for_each_function",for_each_function},
+ {"insert_any",insert_any},
+ {"for_each_any",for_each_any}
+ }};
+
+ if(argc<2){
+ std::cout<<"specify one or more tests to execute:\n";
+ for(const auto& p:tests)std::cout<<" "<<p.first<<"\n";
+ return 1;
+ }
+
+ for(int arg=1;arg<argc;++arg){
+ auto it=std::find_if(tests.begin(),tests.end(),[&](test& t){
+ return t.first==argv[arg];
+ });
+ if(it==tests.end()){
+ std::cout<<"invalid test name\n";
+ return 1;
+ }
+ it->second=true;
+ }
+
+ unsigned int n0=100,n1=10000000,dsav=50; /* sav for savart */
+
+ {
+ auto seq= element_sequence<
+ derived1,derived1,derived2,derived2,derived3>{};
+ auto f= for_each_callable{};
+ auto pv= label<ptr_vector<base>>
+ {"ptr_vector"};
+ auto spv= label<sorted_ptr_vector<base>>
+ {"sorted ptr_vector"};
+ auto shpv= label<shuffled_ptr_vector<base>>
+ {"shuffled ptr_vector"};
+ auto bc= label<base_collection<base>>
+ {"base_collection"};
+ auto fbc= label<poly_for_each_base_collection<base>>
+ {"base_collection (poly::for_each)"};
+ auto rfbc= label<
+ poly_for_each_base_collection<base,derived1,derived2,derived2>
+ >
+ {"base_collection (restituted poly::for_each)"};
+
+ if(all||insert_base)insert_perf(n0,n1,dsav,seq,pv,bc);
+ if(all||for_each_base)for_each_perf(
+ n0,n1,dsav,seq,f,pv,spv,shpv,bc,fbc,rfbc);
+ }
+ {
+ using signature=int(int);
+
+ auto seq= element_sequence<
+ concrete1,concrete1,concrete2,concrete2,concrete3>{};
+ auto f = for_each_callable{};
+ auto fv= label<func_vector<signature>>
+ {"func_vector"};
+ auto sfv= label<sorted_func_vector<signature>>
+ {"sorted func_vector"};
+ auto shfv= label<shuffled_func_vector<signature>>
+ {"shuffled func_vector"};
+ auto fc= label<func_collection<signature>>
+ {"function_collection"};
+ auto ffc= label<poly_for_each_func_collection<signature>>
+ {"function_collection (poly::for_each)"};
+ auto rffc= label<poly_for_each_func_collection<
+ signature,concrete1,concrete2,concrete3>>
+ {"function_collection (restituted poly::for_each)"};
+
+ if(all||insert_function)insert_perf(n0,n1,dsav,seq,fv,fc);
+ if(all||for_each_function)for_each_perf(
+ n0,n1,dsav,seq,f,fv,sfv,shfv,fc,ffc,rffc);
+ }
+ {
+//[perf_any_types
+ using concept_=boost::mpl::vector<
+ boost::type_erasure::copy_constructible<>,
+ boost::type_erasure::relaxed,
+ boost::type_erasure::typeid_<>,
+ boost::type_erasure::incrementable<>
+ >;
+//]
+
+ auto seq= element_sequence<int,int,double,double,char>{};
+ auto f= for_each_incrementable{};
+ auto av= label<any_vector<concept_>>
+ {"any_vector"};
+ auto sav= label<sorted_any_vector<concept_>>
+ {"sorted any_vector"};
+ auto shav= label<shuffled_any_vector<concept_>>
+ {"shuffled any_vector"};
+ auto ac= label<any_collection<concept_>>
+ {"any_collection"};
+ auto fac= label<poly_for_each_any_collection<concept_>>
+ {"any_collection (poly::for_each)"};
+ auto rfac= label<poly_for_each_any_collection<concept_,int,double,char>>
+ {"any_collection (restituted poly::for_each)"};
+
+ if(all||insert_any)insert_perf(n0,n1,dsav,seq,av,ac);
+ if(all||for_each_any)for_each_perf(
+ n0,n1,dsav,seq,f,av,sav,shav,ac,fac,rfac);
+ }
+}
diff --git a/src/boost/libs/poly_collection/example/rolegame.hpp b/src/boost/libs/poly_collection/example/rolegame.hpp
new file mode 100644
index 00000000..cb1e9b1f
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/rolegame.hpp
@@ -0,0 +1,78 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+#ifndef BOOST_POLY_COLLECTION_EXAMPLE_ROLEGAME_HPP
+#define BOOST_POLY_COLLECTION_EXAMPLE_ROLEGAME_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+/* entities of a purported role game used in the examples */
+
+#include <iostream>
+#include <string>
+#include <utility>
+
+//[rolegame_1
+struct sprite
+{
+ sprite(int id):id{id}{}
+ virtual ~sprite()=default;
+ virtual void render(std::ostream& os)const=0;
+
+ int id;
+};
+//]
+
+//[rolegame_2
+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;}
+};
+//]
+
+//[rolegame_3
+struct window
+{
+ window(std::string caption):caption{std::move(caption)}{}
+
+ void display(std::ostream& os)const{os<<"["<<caption<<"]";}
+
+ std::string caption;
+};
+//]
+
+//[rolegame_4
+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;}
+};
+//]
+
+
+#endif
diff --git a/src/boost/libs/poly_collection/example/segmented_structure.cpp b/src/boost/libs/poly_collection/example/segmented_structure.cpp
new file mode 100644
index 00000000..ab5701cd
--- /dev/null
+++ b/src/boost/libs/poly_collection/example/segmented_structure.cpp
@@ -0,0 +1,181 @@
+/* Copyright 2016-2017 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/poly_collection for library home page.
+ */
+
+/* segment-specific operations */
+
+#include <algorithm>
+#include <boost/poly_collection/any_collection.hpp>
+#include <boost/poly_collection/base_collection.hpp>
+#include <boost/type_erasure/operators.hpp>
+#include <memory>
+#include <random>
+#include "rolegame.hpp"
+
+std::ostream& operator<<(std::ostream& os,const sprite& s)
+{
+ s.render(os);
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,const window& w)
+{
+ w.display(os);
+ return os;
+}
+
+int main()
+{
+ boost::base_collection<sprite> c;
+
+//[segmented_structure_1
+//= std::unique_ptr<sprite> make_sprite()
+//= {
+//<-
+ auto make_sprite=[]()->std::unique_ptr<sprite>{
+//->
+ static std::mt19937 gen{92748};
+ static std::discrete_distribution<> rnd{{1,1,1}};
+ static int id=0;
+
+ switch(rnd(gen)){
+//<-
+ default:
+//->
+ 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;
+ }
+//<-
+ };
+//->
+//= }
+//= ...
+//=
+//<-
+ try{
+//->
+ for(int i=0;i<8;++i)c.insert(*make_sprite());
+ // throws boost::poly_collection::unregistered_type
+//<-
+ }catch(boost::poly_collection::unregistered_type&){}
+//->
+//]
+
+//[segmented_structure_2
+ std::cout<<c.is_registered<warrior>()<<"\n"; // prints 0
+ std::cout<<c.is_registered(typeid(warrior))<<"\n"; // alternate syntax
+//]
+
+//[segmented_structure_3
+ c.register_types<warrior,juggernaut,goblin>();
+ // everything works fine now
+ for(int i=0;i<8;++i)c.insert(*make_sprite());
+//]
+
+ using renderable=boost::type_erasure::ostreamable<>;
+//[segmented_structure_4
+ boost::any_collection<renderable> c1,c2;
+//= ... // populate c2
+//=
+//<-
+ c2.insert(window{"pop-up"});
+ try{
+//->
+ c1.insert(*c2.begin()); // throws: actual type of *c2.begin() not known by c1
+//<-
+ }catch(boost::poly_collection::unregistered_type&){}
+//->
+//]
+
+//[segmented_structure_5
+//= ... // 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
+//]
+
+//[segmented_structure_6
+ 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";
+//]
+
+//[segmented_structure_7
+ /*=const char**/ comma="";
+ for(const auto& x:c.segment(typeid(warrior))){
+ std::cout<<comma;
+ x.render(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+//]
+
+//[segmented_structure_8
+ /*=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");
+//<-
+ auto it=x.rank.begin();
+ x.rank.erase(it,it+5); // undo previos op, 5==len("super");
+//->
+ std::cout<<comma;
+ x.render(std::cout);
+ comma=",";
+ }
+ std::cout<<"\n";
+
+//]
+
+ auto render=[&](){
+//[segmented_structure_9
+ const char* comma="";
+ for(auto seg:c.segment_traversal()){
+ for(sprite& s:seg){
+ std::cout<<comma;
+ s.render(std::cout);
+ comma=",";
+ }
+ }
+ std::cout<<"\n";
+//]
+ };
+ render();
+
+//[segmented_structure_10
+ c.reserve<goblin>(100); // no reallocation till we exceed 100 goblins
+ std::cout<<c.capacity<goblin>()<<"\n"; // prints 100
+//]
+
+//[segmented_structure_11
+ c.reserve(1000); // reserve(1000) for each segment
+ std::cout<<c.capacity<warrior>()<<", "
+ <<c.capacity<juggernaut>()<<", "
+ <<c.capacity<goblin>()<<"\n"; // prints 1000, 1000, 1000
+//]
+}