diff options
Diffstat (limited to 'src/boost/libs/poly_collection/example')
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 +//] +} |