diff options
Diffstat (limited to 'src/boost/libs/poly_collection')
55 files changed, 5608 insertions, 0 deletions
diff --git a/src/boost/libs/poly_collection/README.md b/src/boost/libs/poly_collection/README.md new file mode 100644 index 00000000..ec9578ab --- /dev/null +++ b/src/boost/libs/poly_collection/README.md @@ -0,0 +1,33 @@ +# Boost PolyCollection library + +Branch | Travis | AppVeyor | Regression tests +---------|--------|----------|----------------- +develop | [![Build Status](https://travis-ci.org/boostorg/poly_collection.svg?branch=develop)](https://travis-ci.org/boostorg/poly_collection) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/poly_collection?branch=develop&svg=true)](https://ci.appveyor.com/project/joaquintides/poly-collection) | [![Test Results](./test_results.svg)](https://www.boost.org/development/tests/develop/developer/poly_collection.html) +master | [![Build Status](https://travis-ci.org/boostorg/poly_collection.svg?branch=master)](https://travis-ci.org/boostorg/poly_collection) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/poly_collection?branch=master&svg=true)](https://ci.appveyor.com/project/joaquintides/poly-collection) | [![Test Results](./test_results.svg)](https://www.boost.org/development/tests/master/developer/poly_collection.html) + +**Boost.PolyCollection**: fast containers of polymorphic objects. + +[Online docs](http://boost.org/libs/poly_collection) +[Seminal article at bannalia.blogspot.com](http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections.html) + +Typically, polymorphic objects cannot be stored *directly* in regular containers +and need be accessed through an indirection pointer, which introduces performance +problems related to CPU caching and branch prediction. Boost.PolyCollection +implements a +[novel data structure](http://www.boost.org/doc/html/poly_collection/an_efficient_polymorphic_data_st.html) +that is able to contiguously store polymorphic objects without such indirection, +thus providing a value-semantics user interface and better performance. +Three *polymorphic collections* are provided: + +* [`boost::base_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_base_collection) +* [`boost::function_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_function_collection) +* [`boost::any_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_any_collection) + +dealing respectively with classic base/derived or OOP polymorphism, function wrapping +in the spirit of `std::function` and so-called +[*duck typing*](https://en.wikipedia.org/wiki/Duck_typing) as implemented by +[Boost.TypeErasure](http://www.boost.org/libs/type_erasure). + +## Requirements + +Boost.PolyCollection is a header-only library. C++11 support is required. The library has been verified to work with Visual Studio 2015, GCC 4.8 and Clang 3.3. 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 +//] +} diff --git a/src/boost/libs/poly_collection/index.html b/src/boost/libs/poly_collection/index.html new file mode 100644 index 00000000..618639e3 --- /dev/null +++ b/src/boost/libs/poly_collection/index.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN"> +<!-- + 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) +--> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<meta http-equiv="refresh" content="0; URL=../../doc/html/poly_collection.html"> +<title>Boost.PolyCollection Documentation</title> +<link rel="stylesheet" href="doc/style.css" type="text/css"> +</head> + +<body> +Automatic redirection failed, please go to +<a href="../../doc/html/poly_collection.html">../../doc/html/poly_collection.html</a> +</body> +</html> diff --git a/src/boost/libs/poly_collection/meta/explicit-failures-markup.xml b/src/boost/libs/poly_collection/meta/explicit-failures-markup.xml new file mode 100644 index 00000000..488b5096 --- /dev/null +++ b/src/boost/libs/poly_collection/meta/explicit-failures-markup.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 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. +--> +<explicit-failures-markup> + <library name="poly_collection"> + <mark-unusable> + <toolset name="clang*-3.0*"/> + <toolset name="clang*-3.1*"/> + <toolset name="clang*-3.2*"/> + <toolset name="gcc*-3.*"/> + <toolset name="gcc*-4.0*"/> + <toolset name="gcc*-4.1*"/> + <toolset name="gcc*-4.2*"/> + <toolset name="gcc*-4.3*"/> + <toolset name="gcc*-4.4*"/> + <toolset name="gcc*-4.5*"/> + <toolset name="gcc*-4.6*"/> + <toolset name="gcc*-4.7*"/> + <toolset name="qcc*-3.*"/> + <toolset name="qcc*-4.0*"/> + <toolset name="qcc*-4.1*"/> + <toolset name="qcc*-4.2*"/> + <toolset name="qcc*-4.3*"/> + <toolset name="qcc*-4.4*"/> + <toolset name="qcc*-4.5*"/> + <toolset name="qcc*-4.6*"/> + <toolset name="qcc*-4.7*"/> + <toolset name="msvc-7.1"/> + <toolset name="msvc-8.0"/> + <toolset name="msvc-9.0"/> + <toolset name="msvc-10.0"/> + <toolset name="msvc-11.0"/> + <toolset name="msvc-12.0"/> + <note author="Joaquín M López Muñoz" date="18 Jun 2017"> + Compiler's too old for working. + </note> + </mark-unusable> + <mark-unusable> + <toolset name="*98"/> + <note author="Joaquín M López Muñoz" date="18 Jun 2017"> + C++11 or later required. + </note> + </mark-unusable> + </library> +</explicit-failures-markup>
\ No newline at end of file diff --git a/src/boost/libs/poly_collection/meta/libraries.json b/src/boost/libs/poly_collection/meta/libraries.json new file mode 100644 index 00000000..317fd77b --- /dev/null +++ b/src/boost/libs/poly_collection/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "poly_collection", + "name": "PolyCollection", + "authors": [ + "Joaqu\u00edn M L\u00f3pez Mu\u00f1oz" + ], + "description": "Fast containers of polymorphic objects.", + "category": [ + "Containers" + ], + "maintainers": [ + "Joaquin M Lopez Munoz <joaquin.lopezmunoz -at- gmail.com>" + ] +} diff --git a/src/boost/libs/poly_collection/test/Jamfile.v2 b/src/boost/libs/poly_collection/test/Jamfile.v2 new file mode 100644 index 00000000..059e780d --- /dev/null +++ b/src/boost/libs/poly_collection/test/Jamfile.v2 @@ -0,0 +1,43 @@ +# 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. + +import testing ; +import ../../config/checks/config : requires ; + +project + : requirements + [ requires cxx11_noexcept ] # used as a proxy for C++11 support + <toolset>msvc:<cxxflags>-D_SCL_SECURE_NO_WARNINGS + ; + +test-suite "poly_collection" : + [ run test_algorithm.cpp test_algorithm1.cpp + test_algorithm2.cpp test_algorithm3.cpp + test_algorithm_main.cpp + : + : + : <toolset>msvc:<cxxflags>/bigobj + <toolset>gcc:<inlining>on + <toolset>gcc:<optimization>space + <toolset>clang:<inlining>on + <toolset>clang:<optimization>space ] + [ run test_capacity.cpp test_capacity_main.cpp ] + [ run test_comparison.cpp test_comparison_main.cpp ] + [ run test_construction.cpp test_construction_main.cpp + : + : + : <toolset>msvc:<cxxflags>/bigobj + <toolset>gcc:<inlining>on + <toolset>gcc:<optimization>space + <toolset>clang:<inlining>on + <toolset>clang:<optimization>space ] + [ run test_emplacement.cpp test_emplacement_main.cpp ] + [ run test_erasure.cpp test_erasure_main.cpp ] + [ run test_insertion.cpp test_insertion_main.cpp ] + [ run test_iterators.cpp test_iterators_main.cpp ] + [ run test_registration.cpp test_registration_main.cpp ] + ; diff --git a/src/boost/libs/poly_collection/test/any_types.hpp b/src/boost/libs/poly_collection/test/any_types.hpp new file mode 100644 index 00000000..0373f058 --- /dev/null +++ b/src/boost/libs/poly_collection/test/any_types.hpp @@ -0,0 +1,94 @@ +/* Copyright 2016-2018 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_TEST_ANY_TYPES_HPP +#define BOOST_POLY_COLLECTION_TEST_ANY_TYPES_HPP + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/mpl/vector/vector10.hpp> +#include <boost/poly_collection/any_collection.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/call.hpp> +#include <boost/type_erasure/operators.hpp> + +namespace any_types{ + +struct incrementable1 +{ + incrementable1(int n):n{n}{} + incrementable1(incrementable1&&)=default; + incrementable1(const incrementable1&)=delete; + incrementable1& operator=(incrementable1&&)=default; + incrementable1& operator=(const incrementable1&)=delete; + bool operator==(const incrementable1& x)const{return n==x.n;} + incrementable1& operator++(){++n;return *this;} + int n; +}; + +struct incrementable3 +{ + incrementable3():n{-1}{} + incrementable3(int n):n{(double)n}{} + incrementable3& operator++(){++n;return *this;} + double n; +}; + +using concept_=boost::type_erasure::incrementable<>; +using collection=boost::any_collection<concept_>; + +template<typename T=boost::type_erasure::_self> +struct convertible_to_int +{ + static int apply(const T& x){return x;} +}; + +using t1=incrementable1; +using t2=double; +using t3=incrementable3; +using t4=int; +using t5=boost::type_erasure::any< + boost::mpl::vector4< + boost::type_erasure::copy_constructible<>, + boost::type_erasure::assignable<>, + concept_, + convertible_to_int<> + > +>; + +struct to_int +{ + template<typename Concept,typename Tag> + int operator()(const boost::type_erasure::any<Concept,Tag>& x)const + { + using boost::type_erasure::any_cast; + + if(auto p=any_cast<t1*>(&x))return (*this)(*p); + if(auto p=any_cast<t2*>(&x))return (*this)(*p); + if(auto p=any_cast<t3*>(&x))return (*this)(*p); + if(auto p=any_cast<t4*>(&x))return (*this)(*p); + if(auto p=any_cast<t5*>(&x))return (*this)(*p); + else return 0; + } + + int operator()(const t1& x)const{return x.n;} + int operator()(const t2& x)const{return static_cast<int>(x);}; + int operator()(const t3& x)const{return static_cast<int>(x.n);} + int operator()(const t4& x)const{return x;} + int operator()(const t5& x)const + { + return boost::type_erasure::call(convertible_to_int<>{},x); + } +}; + +} /* namespace any_types */ + +#endif diff --git a/src/boost/libs/poly_collection/test/base_types.hpp b/src/boost/libs/poly_collection/test/base_types.hpp new file mode 100644 index 00000000..fcfcb0f6 --- /dev/null +++ b/src/boost/libs/poly_collection/test/base_types.hpp @@ -0,0 +1,92 @@ +/* Copyright 2016-2018 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_TEST_BASE_TYPES_HPP +#define BOOST_POLY_COLLECTION_TEST_BASE_TYPES_HPP + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/poly_collection/base_collection.hpp> + +namespace base_types{ + +struct base +{ + virtual ~base()=default; + virtual int operator()(int)const=0; +}; + +struct derived1 final:base +{ + derived1(int n):n{n}{} + derived1(derived1&&)=default; + derived1(const derived1&)=delete; + derived1& operator=(derived1&&)=default; + derived1& operator=(const derived1&)=delete; + virtual int operator()(int)const{return n;} + bool operator==(const derived1& x)const{return n==x.n;} + int n; +}; + +struct derived2:base +{ + derived2(int n):n{n}{} + derived2(derived2&&)=default; + derived2& operator=(derived2&&)=delete; + virtual int operator()(int x)const{return x*n;} + bool operator==(const derived2& x)const{return n==x.n;} + int n; +}; + +struct derived3:base +{ + derived3():n{-1}{} + derived3(int n):n{n}{} + virtual int operator()(int x)const{return x*x*n;} + int n; +}; + +struct another_base +{ + virtual ~another_base()=default; + char x[5]; +}; + +struct derived4:another_base,derived3 +{ + using derived3::derived3; + virtual int operator()(int x)const{return -(this->derived3::operator()(x));} + bool operator==(const derived4& x)const{return n==x.n;} +}; + +struct derived5:base,another_base +{ + derived5(int n):n{n}{} + virtual int operator()(int x)const{return x*x*x*n;} + int n; +}; + +using collection=boost::base_collection<base>; + +using t1=derived1; +using t2=derived2; +using t3=derived3; +using t4=derived4; +using t5=derived5; + +struct to_int +{ + template<typename F> + int operator()(const F& f)const{return f(1);} +}; + +} /* namespace base_types */ + +#endif diff --git a/src/boost/libs/poly_collection/test/function_types.hpp b/src/boost/libs/poly_collection/test/function_types.hpp new file mode 100644 index 00000000..f8c154ff --- /dev/null +++ b/src/boost/libs/poly_collection/test/function_types.hpp @@ -0,0 +1,144 @@ +/* Copyright 2016-2018 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_TEST_FUNCTION_TYPES_HPP +#define BOOST_POLY_COLLECTION_TEST_FUNCTION_TYPES_HPP + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/poly_collection/function_collection.hpp> +#include <typeinfo> + +namespace function_types{ + +struct function1 final +{ + function1(int n):n{n}{} + function1(function1&&)=default; + function1(const function1&)=delete; + function1& operator=(function1&&)=default; + function1& operator=(const function1&)=delete; + int operator()(int)const{return n;} + friend bool operator==( + const function1& x,const function1& y){return x.n==y.n;} + int n; +}; + +struct function2 +{ + function2(int n):n{n}{} + int operator()(int x)const{return x*n;} + bool operator==(const function2& x)const{return n==x.n;} + int n; +}; + +struct function3 +{ + function3():n{-1}{} + function3(int n):n{n}{} + int operator()(int x)const{return x*x*n;} + int n; +}; + +struct function4:function3 +{ + using function3::function3; + int operator()(int x)const{return -(this->function3::operator()(x));} + bool operator==(const function4& x)const{return n==x.n;} +}; + +struct function5 +{ + function5(int n):n{n}{} + int operator()(int x)const{return x*x*x*n;} + int n; +}; + +struct int_alias /* brings this namespace into ADL for operator== below */ +{ + int_alias(int n):n{n}{} + operator int()const{return n;} + int n; +}; + +using signature=int_alias(int); +using collection=boost::function_collection<signature>; + +using t1=function1; +using t2=function2; +using t3=function3; +using t4=function4; +using t5=function5; + +inline bool operator==( + const collection::value_type& x,const collection::value_type& y) +{ + const std::type_info& xi=x.target_type(); + const std::type_info& yi=y.target_type(); + if(xi==yi){ + if(xi==typeid(t1))return (*x.target<t1>())==(*y.target<t1>()); + if(xi==typeid(t2))return (*x.target<t2>()).operator==(*y.target<t2>()); + if(xi==typeid(t4))return (*x.target<t4>()).operator==(*y.target<t4>()); + } + return false; +} + +inline bool operator==(const collection::value_type& x,const t1& y) +{ + const std::type_info& xi=x.target_type(); + if(xi==typeid(t1))return (*x.target<t1>())==y; + return false; +} + +inline bool operator==(const t1& x,const collection::value_type& y) +{ + return y==x; +} + +inline bool operator==(const collection::value_type& x,const t2& y) +{ + const std::type_info& xi=x.target_type(); + if(xi==typeid(t2))return (*x.target<t2>())==y; + return false; +} + +inline bool operator==(const t2& x,const collection::value_type& y) +{ + return y==x; +} + +inline bool operator==(const collection::value_type& x,const t4& y) +{ + const std::type_info& xi=x.target_type(); + if(xi==typeid(t4))return (*x.target<t4>())==y; + return false; +} + +inline bool operator==(const t4& x,const collection::value_type& y) +{ + return y==x; +} + +inline bool operator==(const t1&,const t2&){return false;} +inline bool operator==(const t1&,const t4&){return false;} +inline bool operator==(const t2&,const t1&){return false;} +inline bool operator==(const t2&,const t4&){return false;} +inline bool operator==(const t4&,const t1&){return false;} +inline bool operator==(const t4&,const t2&){return false;} + +struct to_int +{ + template<typename F> + int operator()(const F& f)const{return f(1);} +}; + +} /* namespace function_types */ + +#endif diff --git a/src/boost/libs/poly_collection/test/test_algorithm.cpp b/src/boost/libs/poly_collection/test/test_algorithm.cpp new file mode 100644 index 00000000..118c96ff --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm.cpp @@ -0,0 +1,21 @@ +/* Copyright 2016 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. + */ + +#include "test_algorithm.hpp" +#include "test_algorithm1.hpp" +#include "test_algorithm2.hpp" +#include "test_algorithm3.hpp" + +/* test split in chunks to avoid problems with compilation object sizes */ + +void test_algorithm() +{ + test_algorithm1(); + test_algorithm2(); + test_algorithm3(); +} diff --git a/src/boost/libs/poly_collection/test/test_algorithm.hpp b/src/boost/libs/poly_collection/test/test_algorithm.hpp new file mode 100644 index 00000000..c687deb0 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_algorithm(); diff --git a/src/boost/libs/poly_collection/test/test_algorithm1.cpp b/src/boost/libs/poly_collection/test/test_algorithm1.cpp new file mode 100644 index 00000000..12e0762d --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm1.cpp @@ -0,0 +1,20 @@ +/* Copyright 2016 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. + */ + +#include "test_algorithm1.hpp" + +#include "any_types.hpp" +#include "test_algorithm_impl.hpp" + +void test_algorithm1() +{ + test_algorithm< + any_types::collection,jammed_auto_increment,any_types::to_int, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_algorithm1.hpp b/src/boost/libs/poly_collection/test/test_algorithm1.hpp new file mode 100644 index 00000000..ae9ddd81 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm1.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_algorithm1(); diff --git a/src/boost/libs/poly_collection/test/test_algorithm2.cpp b/src/boost/libs/poly_collection/test/test_algorithm2.cpp new file mode 100644 index 00000000..ad989497 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm2.cpp @@ -0,0 +1,20 @@ +/* Copyright 2016 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. + */ + +#include "test_algorithm2.hpp" + +#include "base_types.hpp" +#include "test_algorithm_impl.hpp" + +void test_algorithm2() +{ + test_algorithm< + base_types::collection,jammed_auto_increment,base_types::to_int, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_algorithm2.hpp b/src/boost/libs/poly_collection/test/test_algorithm2.hpp new file mode 100644 index 00000000..b18703dc --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm2.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_algorithm2(); diff --git a/src/boost/libs/poly_collection/test/test_algorithm3.cpp b/src/boost/libs/poly_collection/test/test_algorithm3.cpp new file mode 100644 index 00000000..c9303270 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm3.cpp @@ -0,0 +1,20 @@ +/* Copyright 2016 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. + */ + +#include "test_algorithm3.hpp" + +#include "function_types.hpp" +#include "test_algorithm_impl.hpp" + +void test_algorithm3() +{ + test_algorithm< + function_types::collection,jammed_auto_increment,function_types::to_int, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_algorithm3.hpp b/src/boost/libs/poly_collection/test/test_algorithm3.hpp new file mode 100644 index 00000000..5ccc7dbc --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm3.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_algorithm3(); diff --git a/src/boost/libs/poly_collection/test/test_algorithm_impl.hpp b/src/boost/libs/poly_collection/test/test_algorithm_impl.hpp new file mode 100644 index 00000000..1ee8224c --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm_impl.hpp @@ -0,0 +1,1122 @@ +/* Copyright 2016-2018 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_TEST_TEST_ALGORITHM_IMPL_HPP +#define BOOST_POLY_COLLECTION_TEST_TEST_ALGORITHM_IMPL_HPP + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <algorithm> +#include <boost/config.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/function_output_iterator.hpp> +#include <boost/poly_collection/algorithm.hpp> +#include <functional> +#include <iterator> +#include <random> +#include <type_traits> +#include <utility> +#include <vector> +#include "test_utilities.hpp" + +using namespace test_utilities; + +#if BOOST_WORKAROUND(BOOST_MSVC,>=1910) +/* https://lists.boost.org/Archives/boost/2017/06/235687.php */ + +#define DEFINE_ALGORITHM(name,f) \ +template<typename... Ts> \ +struct name \ +{ \ + template<typename... Args> \ + auto operator()(Args&&... args)const \ + { \ + return f<Ts...>(std::forward<Args>(args)...); \ + } \ +}; +#elif BOOST_WORKAROUND(BOOST_GCC_VERSION,<50200) +/* problem here is with return type containing <Ts...> */ + +#define DEFINE_ALGORITHM(name,f) \ +template<typename... Ts> \ +struct name \ +{ \ + template<typename... Args> \ + auto operator()(Args&&... args)const-> \ + decltype(f(std::forward<Args>(args)...)) \ + { \ + return f<Ts...>(std::forward<Args>(args)...); \ + } \ +}; +#else +#define DEFINE_ALGORITHM(name,f) \ +template<typename... Ts> \ +struct name \ +{ \ + template<typename... Args> \ + auto operator()(Args&&... args)const-> \ + decltype(f<Ts...>(std::forward<Args>(args)...)) \ + { \ + return f<Ts...>(std::forward<Args>(args)...); \ + } \ +}; +#endif + +DEFINE_ALGORITHM(std_all_of,std::all_of) +DEFINE_ALGORITHM(poly_all_of,boost::poly_collection::all_of) +DEFINE_ALGORITHM(std_any_of,std::any_of) +DEFINE_ALGORITHM(poly_any_of,boost::poly_collection::any_of) +DEFINE_ALGORITHM(std_none_of,std::none_of) +DEFINE_ALGORITHM(poly_none_of,boost::poly_collection::none_of) +DEFINE_ALGORITHM(std_for_each,std::for_each) +DEFINE_ALGORITHM(poly_for_each,boost::poly_collection::for_each) +DEFINE_ALGORITHM(poly_for_each_n,boost::poly_collection::for_each_n) +DEFINE_ALGORITHM(std_find,std::find) +DEFINE_ALGORITHM(poly_find,boost::poly_collection::find) +DEFINE_ALGORITHM(std_find_if,std::find_if) +DEFINE_ALGORITHM(poly_find_if,boost::poly_collection::find_if) +DEFINE_ALGORITHM(std_find_if_not,std::find_if_not) +DEFINE_ALGORITHM(poly_find_if_not,boost::poly_collection::find_if_not) +DEFINE_ALGORITHM(std_find_end,std::find_end) +DEFINE_ALGORITHM(poly_find_end,boost::poly_collection::find_end) +DEFINE_ALGORITHM(std_find_first_of,std::find_first_of) +DEFINE_ALGORITHM(poly_find_first_of,boost::poly_collection::find_first_of) +DEFINE_ALGORITHM(std_adjacent_find,std::adjacent_find) +DEFINE_ALGORITHM(poly_adjacent_find,boost::poly_collection::adjacent_find) +DEFINE_ALGORITHM(std_count,std::count) +DEFINE_ALGORITHM(poly_count,boost::poly_collection::count) +DEFINE_ALGORITHM(std_count_if,std::count_if) +DEFINE_ALGORITHM(poly_count_if,boost::poly_collection::count_if) +DEFINE_ALGORITHM(std_cpp11_mismatch,std::mismatch) /* note std_cpp11 prefix */ +DEFINE_ALGORITHM(poly_mismatch,boost::poly_collection::mismatch) +DEFINE_ALGORITHM(std_cpp11_equal,std::equal) /* note std_cpp11 prefix */ +DEFINE_ALGORITHM(poly_equal,boost::poly_collection::equal) +DEFINE_ALGORITHM(std_cpp11_is_permutation,std::is_permutation) /* std_cpp11 */ +DEFINE_ALGORITHM(poly_is_permutation,boost::poly_collection::is_permutation) +DEFINE_ALGORITHM(std_search,std::search) +DEFINE_ALGORITHM(poly_search,boost::poly_collection::search) +DEFINE_ALGORITHM(std_search_n,std::search_n) +DEFINE_ALGORITHM(poly_search_n,boost::poly_collection::search_n) +DEFINE_ALGORITHM(std_copy,std::copy) +DEFINE_ALGORITHM(poly_copy,boost::poly_collection::copy) +DEFINE_ALGORITHM(std_copy_n,std::copy_n) +DEFINE_ALGORITHM(poly_copy_n,boost::poly_collection::copy_n) +DEFINE_ALGORITHM(std_copy_if,std::copy_if) +DEFINE_ALGORITHM(poly_copy_if,boost::poly_collection::copy_if) +DEFINE_ALGORITHM(std_move,std::move) +DEFINE_ALGORITHM(poly_move,boost::poly_collection::move) +DEFINE_ALGORITHM(std_transform,std::transform) +DEFINE_ALGORITHM(poly_transform,boost::poly_collection::transform) +DEFINE_ALGORITHM(std_replace_copy,std::replace_copy) +DEFINE_ALGORITHM(poly_replace_copy,boost::poly_collection::replace_copy) +DEFINE_ALGORITHM(std_replace_copy_if,std::replace_copy_if) +DEFINE_ALGORITHM(poly_replace_copy_if,boost::poly_collection::replace_copy_if) +DEFINE_ALGORITHM(std_remove_copy,std::remove_copy) +DEFINE_ALGORITHM(poly_remove_copy,boost::poly_collection::remove_copy) +DEFINE_ALGORITHM(std_remove_copy_if,std::remove_copy_if) +DEFINE_ALGORITHM(poly_remove_copy_if,boost::poly_collection::remove_copy_if) +DEFINE_ALGORITHM(std_unique_copy,std::unique_copy) +DEFINE_ALGORITHM(poly_unique_copy,boost::poly_collection::unique_copy) +DEFINE_ALGORITHM(poly_sample,boost::poly_collection::sample) +DEFINE_ALGORITHM(std_rotate_copy,std::rotate_copy) +DEFINE_ALGORITHM(poly_rotate_copy,boost::poly_collection::rotate_copy) +DEFINE_ALGORITHM(std_is_partitioned,std::is_partitioned) +DEFINE_ALGORITHM(poly_is_partitioned,boost::poly_collection::is_partitioned) +DEFINE_ALGORITHM(std_partition_copy,std::partition_copy) +DEFINE_ALGORITHM(poly_partition_copy,boost::poly_collection::partition_copy) +DEFINE_ALGORITHM(std_partition_point,std::partition_point) +DEFINE_ALGORITHM(poly_partition_point,boost::poly_collection::partition_point) + +template<typename...> +struct std_for_each_n +{ + /* implemented here as the algorithm is C++17 */ + + template<typename InputIterator,typename Size,typename Function> + InputIterator operator()(InputIterator first,Size n,Function f)const + { + for(;n>0;++first,(void)--n)f(*first); + return first; + } +}; + +template<typename... Ts> +struct std_mismatch:std_cpp11_mismatch<Ts...> +{ + using std_cpp11_mismatch<Ts...>::operator(); + + /* C++14 variants */ + + template<typename InputIterator1,typename InputIterator2> + std::pair<InputIterator1,InputIterator2> operator()( + InputIterator1 first1,InputIterator1 last1, + InputIterator2 first2,InputIterator2 last2)const + { + while(first1!=last1&&first2!=last2&&*first1==*first2){ + ++first1; + ++first2; + } + return {first1,first2}; + } + + template<typename InputIterator1,typename InputIterator2,typename Predicate> + std::pair<InputIterator1,InputIterator2> operator()( + InputIterator1 first1,InputIterator1 last1, + InputIterator2 first2,InputIterator2 last2,Predicate pred)const + { + while(first1!=last1&&first2!=last2&&pred(*first1,*first2)){ + ++first1; + ++first2; + } + return {first1,first2}; + } +}; + +template<typename... Ts> +struct std_equal:std_cpp11_equal<Ts...> +{ + using std_cpp11_equal<Ts...>::operator(); + + /* C++14 variants */ + + template<typename InputIterator1,typename InputIterator2> + bool operator()( + InputIterator1 first1,InputIterator1 last1, + InputIterator2 first2,InputIterator2 last2)const + { + for(;first1!=last1&&first2!=last2;++first1,++first2){ + if(!(*first1==*first2))return false; + } + return first1==last1&&first2==last2; + } + + template<typename InputIterator1,typename InputIterator2,typename Predicate> + bool operator()( + InputIterator1 first1,InputIterator1 last1, + InputIterator2 first2,InputIterator2 last2,Predicate pred)const + { + for(;first1!=last1&&first2!=last2;++first1,++first2){ + if(!pred(*first1,*first2))return false; + } + return first1==last1&&first2==last2; + } +}; + +template<typename... Ts> +struct std_is_permutation:std_cpp11_is_permutation<Ts...> +{ + using std_cpp11_is_permutation<Ts...>::operator(); + + /* The implementation of predicate-based std::is_permutation in GCC<=4.8 + * version of libstdc++-v3 incorrectly triggers the instantiation of + * ForwardIterator2::value_type, which fails when this is an abstract class. + * The implementation below ripped from libc++ source code. + */ + + template< + typename ForwardIterator1,typename ForwardIterator2,typename Predicate + > + bool operator()( + ForwardIterator1 first1,ForwardIterator1 last1, + ForwardIterator2 first2,Predicate pred)const + { + using difference_type= + typename std::iterator_traits<ForwardIterator1>::difference_type; + + for(;first1!=last1;++first1,(void)++first2){ + if(!pred(*first1,*first2))goto not_done; + } + return true; + + not_done: + difference_type l1=std::distance(first1,last1); + if(l1==difference_type(1))return false; + + ForwardIterator2 last2=std::next(first2,l1); + for(ForwardIterator1 i=first1;i!= last1;++i){ + for(ForwardIterator1 j=first1;j!=i;++j)if(pred(*j,*i))goto next_iter; + { + difference_type c2=0; + for(ForwardIterator2 j=first2;j!=last2;++j)if(pred(*i,*j))++c2; + if(c2==0)return false; + difference_type c1=1; + for(ForwardIterator1 j=std::next(i);j!=last1;++j)if(pred(*i,*j))++c1; + if(c1!=c2)return false; + } + next_iter:; + } + return true; + } + + /* C++14 variants */ + + template<typename ForwardIterator1,typename ForwardIterator2> + bool operator()( + ForwardIterator1 first1,ForwardIterator1 last1, + ForwardIterator2 first2,ForwardIterator2 last2)const + { + if(std::distance(first1,last1)!=std::distance(first2,last2))return false; + return (*this)(first1,last1,first2); + } + + template< + typename ForwardIterator1,typename ForwardIterator2,typename Predicate + > + bool operator()( + ForwardIterator1 first1,ForwardIterator1 last1, + ForwardIterator2 first2,ForwardIterator2 last2,Predicate pred)const + { + if(std::distance(first1,last1)!=std::distance(first2,last2))return false; + return (*this)(first1,last1,first2,pred); + } +}; + +template<typename...> +struct std_sample +{ + /* Implemented here as the algorithm is C++17 and because we need to control + * the implementation to do white-box testing. Only the ForwardIterator + * version required. + */ + + template< + typename ForwardIterator,typename OutputIterator, + typename Distance, typename UniformRandomBitGenerator + > + OutputIterator operator()( + ForwardIterator first,ForwardIterator last, + OutputIterator res, Distance n,UniformRandomBitGenerator&& g)const + { + Distance m=std::distance(first,last); + for(n=(std::min)(n,m);n!=0;++first){ + auto r=std::uniform_int_distribution<Distance>(0,--m)(g); + if (r<n){ + *res++=*first; + --n; + } + } + return res; + } +}; + +template< + typename ControlAlgorithm,typename Algorithm, + typename PolyCollection,typename... Args +> +void test_algorithm(PolyCollection& p,Args&&... args) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto last=first;;++last){ + BOOST_TEST( + alg(first,last,std::forward<Args>(args)...)== + control(first,last,std::forward<Args>(args)...)); + if(last==end)break; + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename PolyCollection,typename... Args +> +void test_algorithms(PolyCollection& p,Args&&... args) +{ + do_((test_algorithm<ControlAlgorithm,Algorithms>( + p,std::forward<Args>(args)...),0)...); + do_((test_algorithm<ControlAlgorithm,Algorithms>( + const_cast<const PolyCollection&>(p),std::forward<Args>(args)...),0)...); +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename PolyCollection,typename... Args +> +void test_algorithms_with_equality_impl( + std::true_type,PolyCollection& p,Args&&... args) +{ + test_algorithms<ControlAlgorithm,Algorithms...>( + p,std::forward<Args>(args)...); +} + +template< + typename ControlAlgorithm,typename... Algorithm, + typename PolyCollection,typename... Args +> +void test_algorithms_with_equality_impl( + std::false_type,PolyCollection&,Args&&...) +{ +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename PolyCollection,typename... Args +> +void test_algorithms_with_equality(PolyCollection& p,Args&&... args) +{ + test_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>( + is_equality_comparable<typename PolyCollection::value_type>{}, + p,std::forward<Args>(args)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection +> +void test_for_each_n_algorithm(ToInt to_int,PolyCollection& p) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto n=std::distance(first,end);n>=0;--n){ + int res1=0,res2=0; + auto acc1=compose(to_int,[&](int x){res1+=x;}); + auto acc2=compose(to_int,[&](int x){res2+=x;}); + auto it1=alg(first,n,acc1), + it2=control(first,n,acc2); + BOOST_TEST(it1==it2); + BOOST_TEST(res1==res2); + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection +> +void test_for_each_n_algorithms(ToInt to_int,PolyCollection& p) +{ + do_((test_for_each_n_algorithm<ControlAlgorithm,Algorithms>( + to_int,p),0)...); + do_((test_for_each_n_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p)),0)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_algorithm(ToInt to_int,PolyCollection& p,Args&&... args) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto last=first;;++last){ + using vector=std::vector<int>; + + vector v1,v2; + auto insert1=compose(to_int,[&](int x){v1.push_back(x);}); + auto insert2=compose(to_int,[&](int x){v2.push_back(x);}); + auto out1=boost::make_function_output_iterator(std::ref(insert1)); + auto out2=boost::make_function_output_iterator(std::ref(insert2)); + + out1=alg(first,last,out1,std::forward<Args>(args)...); + out2=control(first,last,out2,std::forward<Args>(args)...); + BOOST_TEST(v1==v2); + if(last==end)break; + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_algorithms(ToInt to_int,PolyCollection& p,Args&&... args) +{ + do_((test_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,p,std::forward<Args>(args)...),0)...); + do_((test_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p), + std::forward<Args>(args)...),0)...); +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_algorithms_with_equality_impl( + std::true_type,ToInt to_int,PolyCollection& p,Args&&... args) +{ + test_copy_algorithms<ControlAlgorithm,Algorithms...>( + to_int,p,std::forward<Args>(args)...); +} + +template< + typename ControlAlgorithm,typename... Algorithm, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_algorithms_with_equality_impl( + std::false_type,ToInt,PolyCollection&,Args&&...) +{ +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_algorithms_with_equality( + ToInt to_int,PolyCollection& p,Args&&... args) +{ + test_copy_algorithms_with_equality_impl<ControlAlgorithm,Algorithms...>( + is_equality_comparable<typename PolyCollection::value_type>{}, + to_int,p,std::forward<Args>(args)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_n_algorithm(ToInt to_int,PolyCollection& p,Args&&... args) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(std::ptrdiff_t n=0,m=std::distance(first,end);n<=m;++n){ + using vector=std::vector<int>; + + vector v1,v2; + auto insert1=compose(to_int,[&](int x){v1.push_back(x);}); + auto insert2=compose(to_int,[&](int x){v2.push_back(x);}); + auto out1=boost::make_function_output_iterator(std::ref(insert1)); + auto out2=boost::make_function_output_iterator(std::ref(insert2)); + + alg(first,n,out1,std::forward<Args>(args)...); + control(first,n,out2,std::forward<Args>(args)...); + BOOST_TEST(v1==v2); + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection,typename... Args +> +void test_copy_n_algorithms(ToInt to_int,PolyCollection& p,Args&&... args) +{ + do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>( + to_int,p,std::forward<Args>(args)...),0)...); + do_((test_copy_n_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p), + std::forward<Args>(args)...),0)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection +> +void test_transform2_algorithm(ToInt to_int,PolyCollection& p) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto last=first;;++last){ + using vector=std::vector<int>; + + auto op=compose_all(to_int,[](int x,int y){return x+y;}); + vector v1,v2; + auto insert1=[&](int x){v1.push_back(x);}; + auto insert2=[&](int x){v2.push_back(x);}; + auto out1=boost::make_function_output_iterator(std::ref(insert1)); + auto out2=boost::make_function_output_iterator(std::ref(insert2)); + + out1=alg(first,last,p.begin(),out1,op); + out2=control(first,last,p.begin(),out2,op); + BOOST_TEST(v1==v2); + if(last==end)break; + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection +> +void test_transform2_algorithms(ToInt to_int,PolyCollection& p) +{ + do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>( + to_int,p),0)...); + do_((test_transform2_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p)),0)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection +> +void test_rotate_copy_algorithm(ToInt to_int,PolyCollection& p) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto last=first;;++last){ + for(auto middle=first;;++middle){ + using vector=std::vector<int>; + + vector v1,v2; + auto insert1=compose(to_int,[&](int x){v1.push_back(x);}); + auto insert2=compose(to_int,[&](int x){v2.push_back(x);}); + auto out1=boost::make_function_output_iterator(std::ref(insert1)); + auto out2=boost::make_function_output_iterator(std::ref(insert2)); + + out1=alg(first,middle,last,out1); + out2=control(first,middle,last,out2); + BOOST_TEST(v1==v2); + + if(middle==last)break; + } + if(last==end)break; + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection +> +void test_rotate_copy_algorithms(ToInt to_int,PolyCollection& p) +{ + do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,p),0)...); + do_((test_rotate_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p)),0)...); +} + +template< + typename ControlAlgorithm,typename Algorithm, + typename ToInt,typename PolyCollection,typename Predicate +> +void test_partition_copy_algorithm( + ToInt to_int,PolyCollection& p,Predicate pred) +{ + Algorithm alg; + ControlAlgorithm control; + for(auto first=p.begin(),end=p.end();;++first){ + for(auto last=first;;++last){ + using vector=std::vector<int>; + + vector v11,v12,v21,v22; + auto insert11=compose(to_int,[&](int x){v11.push_back(x);}); + auto insert12=compose(to_int,[&](int x){v12.push_back(x);}); + auto insert21=compose(to_int,[&](int x){v21.push_back(x);}); + auto insert22=compose(to_int,[&](int x){v22.push_back(x);}); + auto out11=boost::make_function_output_iterator(std::ref(insert11)); + auto out12=boost::make_function_output_iterator(std::ref(insert12)); + auto out21=boost::make_function_output_iterator(std::ref(insert21)); + auto out22=boost::make_function_output_iterator(std::ref(insert22)); + + std::tie(out11,out12)=alg(first,last,out11,out12,pred); + std::tie(out21,out22)=control(first,last,out21,out22,pred); + BOOST_TEST(v11==v21); + BOOST_TEST(v12==v22); + if(last==end)break; + } + if(first==end)break; + } +} + +template< + typename ControlAlgorithm,typename... Algorithms, + typename ToInt,typename PolyCollection,typename Predicate +> +void test_partition_copy_algorithms( + ToInt to_int,PolyCollection& p,Predicate pred) +{ + do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,p,pred),0)...); + do_((test_partition_copy_algorithm<ControlAlgorithm,Algorithms>( + to_int,const_cast<const PolyCollection&>(p),pred),0)...); +} + +template<typename ToInt> +struct poly_accumulator_class +{ + poly_accumulator_class(const ToInt& to_int):res{0},to_int(to_int){} + bool operator==(const poly_accumulator_class& x)const{return res==x.res;} + + template<typename T> void operator()(const T& x){res+=to_int(x);} + + int res; + ToInt to_int; +}; + +template<typename ToInt> +poly_accumulator_class<ToInt> poly_accumulator(const ToInt& to_int) +{ + return to_int; +} + +template<typename Algorithm> +struct force_arg_copying +{ + Algorithm alg; + + template<typename T> + static T copy(const T& x){return x;} + + template<typename... Args> + auto operator()(Args&&... args)const + ->decltype(std::declval<Algorithm>()(copy(args)...)) + { + return alg(copy(args)...); + } +}; + +template< + typename PolyCollection,typename ValueFactory,typename ToInt, + typename... Types +> +void test_algorithm() +{ + PolyCollection p; + ValueFactory v; + ToInt to_int; + + fill<constraints<>,Types...>(p,v,2); + + { + auto always_true=compose(to_int,[](int){return true;}); + auto always_false=compose(to_int,[](int){return false;}); + auto pred=compose(to_int,[](int x){return x%2==0;}); + + test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>( + p,always_true); + test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>( + p,always_false); + test_algorithms<std_all_of<>,poly_all_of<>,poly_all_of<Types...>>( + p,pred); + + test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>( + p,always_true); + test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>( + p,always_false); + test_algorithms<std_any_of<>,poly_any_of<>,poly_any_of<Types...>>( + p,pred); + + test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>( + p,always_true); + test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>( + p,always_false); + test_algorithms<std_none_of<>,poly_none_of<>,poly_none_of<Types...>>( + p,pred); + } + { + test_algorithms<std_for_each<>,poly_for_each<>,poly_for_each<Types...>>( + p,poly_accumulator(to_int)); + + test_for_each_n_algorithms< + std_for_each_n<>,poly_for_each_n<>,poly_for_each_n<Types...> + >(to_int,p); + } + { + for(const auto& x:p){ + test_algorithms_with_equality< + std_find<>,poly_find<>,only_eq_comparable<poly_find,Types...> + >(p,x); + } + } + { + auto it=p.begin(); + std::advance(it,p.size()/2); + int n=to_int(*it); + auto pred=compose(to_int,[=](int x){return x==n;}); + + test_algorithms<std_find_if<>,poly_find_if<>,poly_find_if<Types...>>( + p,pred); + + test_algorithms< + std_find_if_not<>,poly_find_if_not<>,poly_find_if_not<Types...> + >(p,pred); + } + { + auto first=p.begin(),end=first; + std::advance(end,+p.size()/2); + for(;first!=end;++first){ + test_algorithms_with_equality< + std_find_end<>,poly_find_end<>, + only_eq_comparable<poly_find_end,Types...> + >(p,first,end); + + test_algorithms_with_equality< + std_search<>,poly_search<>, + only_eq_comparable<poly_search,Types...> + >(p,first,end); + } + } + { + std::vector<int> v; + for(const auto& x:p)v.push_back(to_int(x)); + v.erase(v.begin()+v.size()/2,v.end()); + + for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){ + for(int i=1;i<4;++i){ + auto pred=compose(to_int,[&](int x,int y){return x%i==y%i;}); + + test_algorithms< + std_find_end<>,poly_find_end<>,poly_find_end<Types...> + >(p,first,end,pred); + + test_algorithms<std_search<>,poly_search<>,poly_search<Types...>>( + p,first,end,pred); + } + } + } + { + using value_type=typename PolyCollection::value_type; + using vector=std::vector<std::reference_wrapper<const value_type>>; + + vector v; + for(const auto& x:p){ + switch(v.size()%3){ + case 0:v.push_back(x);break; + case 1:v.push_back(*p.begin());break; + default:{} + } + } + + for(auto first=v.begin(),end=v.end();;++first){ + for(auto last=first;;++last){ + test_algorithms_with_equality< + std_find_first_of<>,poly_find_first_of<>, + only_eq_comparable<poly_find_first_of,Types...> + >(p,first,last); + if(last==end)break; + } + if(first==end)break; + } + } + { + std::vector<int> v; + for(const auto& x:p){ + switch(v.size()%3){ + case 0:v.push_back(to_int(x));break; + case 1:v.push_back(-1);break; + default:{} + } + } + + for(auto first=v.begin(),end=v.end();;++first){ + for(auto last=first;;++last){ + test_algorithms< + std_find_first_of<>,poly_find_first_of<>,poly_find_first_of<Types...> + >(p,first,last,compose(to_int,std::equal_to<int>{})); + if(last==end)break; + } + if(first==end)break; + } + } + { + test_algorithms_with_equality< + std_adjacent_find<>,poly_adjacent_find<>, + only_eq_comparable<poly_adjacent_find,Types...> + >(p); + } + { + std::vector<int> v; + for(const auto& x:p)v.push_back(to_int(x)); + v.push_back(-1); + + for(auto first=v.begin(),end=v.end()-1;first!=end;++first){ + int n1=*first,n2=*(first+1); + test_algorithms< + std_adjacent_find<>,poly_adjacent_find<>,poly_adjacent_find<Types...> + >(p,compose_all(to_int,[=](int x,int y){return x==n1&&y==n2;})); + } + } + { + for(const auto& x:p){ + test_algorithms_with_equality< + std_count<>,poly_count<>,only_eq_comparable<poly_count,Types...> + >(p,x); + } + } + { + for(int i=1;i<4;++i){ + test_algorithms<std_count_if<>,poly_count_if<>,poly_count_if<Types...>>( + p,compose(to_int,[&](int x){return x%i==0;})); + } + } + { + using value_type=typename PolyCollection::value_type; + using vector=std::vector<std::reference_wrapper<const value_type>>; + + vector v; + for(const auto& x:p)v.push_back(x); + v.back()=v.front(); + auto w=v; + v.insert(v.end(),w.begin(),w.end()); + + for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){ + test_algorithms_with_equality< + std_mismatch<>,poly_mismatch<>, + only_eq_comparable<poly_mismatch,Types...> + >(p,first); + + test_algorithms_with_equality< + std_mismatch<>,poly_mismatch<>, + only_eq_comparable<poly_mismatch,Types...> + >(p,first,end); + + test_algorithms_with_equality< + std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...> + >(p,first); + + test_algorithms_with_equality< + std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...> + >(p,first,end); + } + + test_algorithms_with_equality< + std_mismatch<>,poly_mismatch<>,only_eq_comparable<poly_mismatch,Types...> + >(p,v.end(),v.end()); + + test_algorithms_with_equality< + std_equal<>,poly_equal<>,only_eq_comparable<poly_equal,Types...> + >(p,v.end(),v.end()); + } + { + std::vector<int> v; + for(const auto& x:p)v.push_back(to_int(x)); + v.back()=-1; + auto w=v; + v.insert(v.end(),w.begin(),w.end()); + auto pred=compose(to_int,std::equal_to<int>{}); + + for(auto first=v.begin(),end=v.begin()+v.size()/2;first!=end;++first){ + test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>( + p,first,pred); + + test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>( + p,first,end,pred); + + test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>( + p,first,pred); + + test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>( + p,first,end,pred); + } + + test_algorithms<std_mismatch<>,poly_mismatch<>,poly_mismatch<Types...>>( + p,v.end(),v.end(),pred); + + test_algorithms<std_equal<>,poly_equal<>,poly_equal<Types...>>( + p,v.end(),v.end(),pred); + } + { + using value_type=typename PolyCollection::value_type; + using vector=std::vector<std::reference_wrapper<const value_type>>; + + vector v; + for(const auto& x:p)v.push_back(x); + auto w=v; + std::mt19937 gen{73642}; + std::shuffle(w.begin(),w.end(),gen); + v.insert(v.end(),w.begin(),w.end()); + auto pred=compose_all(to_int,std::equal_to<int>{}); + + for(auto first=unwrap_iterator(v.begin()), + end=unwrap_iterator(v.begin()+v.size()/2);first!=end;++first){ + test_algorithms_with_equality< + std_is_permutation<>, + poly_is_permutation<>, + only_eq_comparable<poly_is_permutation,Types...> + >(p,first); + + test_algorithms< + std_is_permutation<>, + poly_is_permutation<>,poly_is_permutation<Types...> + >(p,first,pred); + + test_algorithms_with_equality< + std_is_permutation<>, + poly_is_permutation<>, + only_eq_comparable<poly_is_permutation,Types...> + >(p,first,end); + + test_algorithms< + std_is_permutation<>, + poly_is_permutation<>,poly_is_permutation<Types...> + >(p,first,end,pred); + } + + test_algorithms_with_equality< + std_is_permutation<>, + poly_is_permutation<>, + only_eq_comparable<poly_is_permutation,Types...> + >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end())); + + test_algorithms< + std_is_permutation<>, + poly_is_permutation<>,poly_is_permutation<Types...> + >(p,unwrap_iterator(v.end()),unwrap_iterator(v.end()),pred); + } + { + /* search tested above */ + } + { + for(const auto&x: p){ + for(int n=0;n<3;++n){ + test_algorithms_with_equality< + std_search_n<>,poly_search_n<>, + only_eq_comparable<poly_search_n,Types...> + >(p,n,x); + } + } + } + { + for(int n=0;n<6;++n){ + test_algorithms<std_search_n<>,poly_search_n<>,poly_search_n<Types...>>( + p,n,0,compose(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);})); + } + } + { + test_copy_algorithms<std_copy<>,poly_copy<>,poly_copy<Types...>>( + to_int,p); + } + { + test_copy_n_algorithms<std_copy_n<>,poly_copy_n<>,poly_copy_n<Types...>>( + to_int,p); + } + { + auto always_true=compose(to_int,[](int){return true;}); + auto always_false=compose(to_int,[](int){return false;}); + auto pred=compose(to_int,[](int x){return x%2==0;}); + + test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>( + to_int,p,always_true); + test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>( + to_int,p,always_false); + test_copy_algorithms<std_copy_if<>,poly_copy_if<>,poly_copy_if<Types...>>( + to_int,p,pred); + } + { + test_copy_algorithms<std_move<>,poly_move<>,poly_move<Types...>>( + to_int,p); /* we're not checking std::move is properly used internally */ + } + { + auto f=compose(to_int,[](int x){return -x;}); + auto int_id=[](int x){return x;}; + + test_copy_algorithms< + std_transform<>,poly_transform<>,poly_transform<Types...> + >(int_id,p,f); + } + { + test_transform2_algorithms< + std_transform<>,poly_transform<>,poly_transform<Types...> + >(to_int,p); + } + { + const auto& y=*p.begin(); + for(const auto& x:p){ + test_copy_algorithms_with_equality< + std_replace_copy<>,poly_replace_copy<>, + only_eq_comparable<poly_replace_copy,Types...> + >(to_int,p,x,y); + + test_copy_algorithms_with_equality< + std_remove_copy<>,poly_remove_copy<>, + only_eq_comparable<poly_remove_copy,Types...> + >(to_int,p,x); + } + } + { + auto always_true=compose(to_int,[](int){return true;}); + auto always_false=compose(to_int,[](int){return false;}); + auto pred=compose(to_int,[](int x){return x%2==0;}); + auto& x=*p.begin(); + + test_copy_algorithms< + std_replace_copy_if<>, + poly_replace_copy_if<>,poly_replace_copy_if<Types...> + >(to_int,p,always_true,x); + test_copy_algorithms< + std_replace_copy_if<>, + poly_replace_copy_if<>,poly_replace_copy_if<Types...> + >(to_int,p,always_false,x); + test_copy_algorithms< + std_replace_copy_if<>, + poly_replace_copy_if<>,poly_replace_copy_if<Types...> + >(to_int,p,pred,x); + + test_copy_algorithms< + std_remove_copy_if<>, + poly_remove_copy_if<>,poly_remove_copy_if<Types...> + >(to_int,p,always_true); + test_copy_algorithms< + std_remove_copy_if<>, + poly_remove_copy_if<>,poly_remove_copy_if<Types...> + >(to_int,p,always_false); + test_copy_algorithms< + std_remove_copy_if<>, + poly_remove_copy_if<>,poly_remove_copy_if<Types...> + >(to_int,p,pred); + } + { + test_copy_algorithms_with_equality< + std_unique_copy<>,poly_unique_copy<>, + only_eq_comparable<poly_unique_copy,Types...> + >(to_int,p); + } + { + for(int n=0;n<6;++n){ + test_copy_algorithms< + std_unique_copy<>,poly_unique_copy<>,poly_unique_copy<Types...> + >(to_int,p, + compose_all(to_int,[&](int x,int y){return x%(6-n)==y%(6-n);})); + } + } + { + test_rotate_copy_algorithms< + std_rotate_copy<>,poly_rotate_copy<>,poly_rotate_copy<Types...> + >(to_int,p); + } + { + /* force_arg_copying used to avoid sharing mt19937's state */ + + for(auto n=p.size()+1;n-->0;){ + test_copy_algorithms< + force_arg_copying<std_sample<>>, + force_arg_copying<poly_sample<>>, + force_arg_copying<poly_sample<Types...>> + >(to_int,p,n,std::mt19937{}); + } + } + { + for(int n=0;n<6;++n){ + auto pred=compose(to_int,[&](int x){return x%(6-n)<=(6-n)/2;}); + + test_algorithms< + std_is_partitioned<>, + poly_is_partitioned<>,poly_is_partitioned<Types...> + >(p,pred); + + test_partition_copy_algorithms< + std_partition_copy<>, + poly_partition_copy<>,poly_partition_copy<Types...> + >(to_int,p,pred); + + test_algorithms< + std_partition_point<>, + poly_partition_point<>,poly_partition_point<Types...> + >(p,pred); + } + } +} + +#endif diff --git a/src/boost/libs/poly_collection/test/test_algorithm_main.cpp b/src/boost/libs/poly_collection/test/test_algorithm_main.cpp new file mode 100644 index 00000000..bb013d9d --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_algorithm_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_algorithm.hpp" + +int main() +{ + test_algorithm(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_all_main.cpp b/src/boost/libs/poly_collection/test/test_all_main.cpp new file mode 100644 index 00000000..162185ba --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_all_main.cpp @@ -0,0 +1,33 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_algorithm.hpp" +#include "test_capacity.hpp" +#include "test_comparison.hpp" +#include "test_construction.hpp" +#include "test_emplacement.hpp" +#include "test_erasure.hpp" +#include "test_insertion.hpp" +#include "test_iterators.hpp" +#include "test_registration.hpp" + +int main() +{ + test_algorithm(); + test_capacity(); + test_comparison(); + test_construction(); + test_emplacement(); + test_erasure(); + test_insertion(); + test_iterators(); + test_registration(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_capacity.cpp b/src/boost/libs/poly_collection/test/test_capacity.cpp new file mode 100644 index 00000000..f47d1ee8 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_capacity.cpp @@ -0,0 +1,92 @@ +/* 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. + */ + +#include "test_capacity.hpp" + +#include <algorithm> +#include <boost/core/lightweight_test.hpp> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_capacity() +{ + PolyCollection p; + const PolyCollection& cp=p; + ValueFactory v; + + BOOST_TEST(cp.empty()); + BOOST_TEST(cp.size()==0); + + p.template register_types<Types...>(); + BOOST_TEST(cp.empty()); + do_((BOOST_TEST(cp.empty(typeid(Types))),0)...); + do_((BOOST_TEST(cp.template empty<Types>()),0)...); + BOOST_TEST(cp.size()==0); + do_((BOOST_TEST(cp.size(typeid(Types))==0),0)...); + do_((BOOST_TEST(cp.template size<Types>()==0),0)...); + + p.reserve(10); + do_((BOOST_TEST(cp.capacity(typeid(Types))>=10),0)...); + do_((BOOST_TEST( + cp.template capacity<Types>()==cp.capacity(typeid(Types))),0)...); + + do_((p.reserve(typeid(Types),20),0)...); + do_((BOOST_TEST(cp.capacity(typeid(Types))>=20),0)...); + + do_((p.template reserve<Types>(30),0)...); + do_((BOOST_TEST(cp.template capacity<Types>()>=30),0)...); + + fill<constraints<>,Types...>(p,v,30); + BOOST_TEST(cp.size()==30*sizeof...(Types)); + do_((BOOST_TEST(cp.size(typeid(Types))==30),0)...); + do_((BOOST_TEST(cp.template size<Types>()==cp.size(typeid(Types))),0)...); + + auto min_capacity=[&]{ + return (std::min)({cp.template capacity<Types>()...}); + }; + + p.reserve(min_capacity()+1); + BOOST_TEST(cp.size()==30*sizeof...(Types)); + + auto c=min_capacity(); + p.shrink_to_fit(); + BOOST_TEST(c>=min_capacity()); + c=min_capacity(); + + do_((p.erase(cp.template begin<Types>()),0)...); + BOOST_TEST(c==min_capacity()); + + do_((p.shrink_to_fit(typeid(Types)),0)...); + BOOST_TEST(c>=min_capacity()); + c=min_capacity(); + + p.clear(); + do_((p.template shrink_to_fit<Types>(),0)...); + BOOST_TEST(c>=min_capacity()); +} + +void test_capacity() +{ + test_capacity< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_capacity< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_capacity< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_capacity.hpp b/src/boost/libs/poly_collection/test/test_capacity.hpp new file mode 100644 index 00000000..8062d193 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_capacity.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_capacity(); diff --git a/src/boost/libs/poly_collection/test/test_capacity_main.cpp b/src/boost/libs/poly_collection/test/test_capacity_main.cpp new file mode 100644 index 00000000..297ee33d --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_capacity_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_capacity.hpp" + +int main() +{ + test_capacity(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_comparison.cpp b/src/boost/libs/poly_collection/test/test_comparison.cpp new file mode 100644 index 00000000..8a767902 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_comparison.cpp @@ -0,0 +1,173 @@ +/* Copyright 2016-2018 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. + */ + +#include "test_comparison.hpp" + +#include <boost/core/lightweight_test.hpp> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_comparison() +{ + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + + BOOST_TEST(cp1==cp1); + BOOST_TEST(!(cp1!=cp1)); + BOOST_TEST(cp1==cp2); + BOOST_TEST(!(cp1!=cp2)); + } + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + fill< + constraints<is_not_equality_comparable>, + Types... + >(p1,v,2); + + BOOST_TEST(!(cp1==cp2)); + BOOST_TEST(cp1!=cp2); + } + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + p1.template register_types<Types...>(); + fill< + constraints<is_not_equality_comparable>, + Types... + >(p1,v,2); + + BOOST_TEST(!(cp1==cp2)); + BOOST_TEST(cp1!=cp2); + } + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + fill< + constraints<is_not_equality_comparable>, + Types... + >(p1,v,1); + fill< + constraints<is_not_equality_comparable>, + Types... + >(p2,v,2); + + BOOST_TEST(!(cp1==cp2)); + BOOST_TEST(cp1!=cp2); + } + { + using not_equality_comparable= + boost::poly_collection::not_equality_comparable; + + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + fill< + constraints<is_not_equality_comparable>, + Types... + >(p1,v,2); + fill< + constraints<is_not_equality_comparable>, + Types... + >(p2,v,2); + + check_throw<not_equality_comparable>( + [&]{(void)(cp1==cp2);}, + [&]{(void)(cp1!=cp2);}); + } + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + fill< + constraints<is_not_equality_comparable>, + Types... + >(p1,v,2); + fill< + constraints<is_equality_comparable,is_copy_constructible>, + Types... + >(p2,v,2); + p1.insert(p2.begin(),p2.end()); + + BOOST_TEST(!(cp1==cp2)); + BOOST_TEST(cp1!=cp2); + } + { + PolyCollection p1,p2; + const PolyCollection& cp1=p1; + const PolyCollection& cp2=p2; + ValueFactory v; + + p1.template register_types<Types...>(); + fill< + constraints<is_equality_comparable,is_copy_constructible>, + Types... + >(p2,v,2); + p1.insert(p2.begin(),p2.end()); + + BOOST_TEST(cp1==cp2); + BOOST_TEST(!(cp1!=cp2)); + + p1.erase(p1.begin()); + BOOST_TEST(!(cp1==cp2)); + BOOST_TEST(cp1!=cp2); + } +} + +void test_stateless_lambda_comparability_check() +{ + /* https://svn.boost.org/trac10/ticket/13012 */ + + { + boost::function_collection<void()> c1,c2; + c1.insert([]{}); + BOOST_TEST(c1!=c2); + } + { + boost::function_collection<int(int)> c1,c2; + c1.insert([](int){return 0;}); + BOOST_TEST(c1!=c2); + } +} + +void test_comparison() +{ + test_comparison< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_comparison< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_comparison< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); + test_stateless_lambda_comparability_check(); +} diff --git a/src/boost/libs/poly_collection/test/test_comparison.hpp b/src/boost/libs/poly_collection/test/test_comparison.hpp new file mode 100644 index 00000000..2ce71142 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_comparison.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_comparison(); diff --git a/src/boost/libs/poly_collection/test/test_comparison_main.cpp b/src/boost/libs/poly_collection/test/test_comparison_main.cpp new file mode 100644 index 00000000..250dccbb --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_comparison_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_comparison.hpp" + +int main() +{ + test_comparison(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_construction.cpp b/src/boost/libs/poly_collection/test/test_construction.cpp new file mode 100644 index 00000000..b1baa6ea --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_construction.cpp @@ -0,0 +1,384 @@ +/* Copyright 2016-2019 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. + */ + +#include "test_construction.hpp" + +#include <algorithm> +#include <boost/config.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/type_erasure/relaxed.hpp> +#include <scoped_allocator> +#include <utility> +#include <vector> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template< + bool Propagate,bool AlwaysEqual, + typename PolyCollection,typename ValueFactory,typename... Types +> +void test_allocator_aware_construction() +{ + using rooted_poly_collection=realloc_poly_collection< + PolyCollection,rooted_allocator, + std::integral_constant<bool,Propagate>, + std::integral_constant<bool,AlwaysEqual>>; + using allocator_type=typename rooted_poly_collection::allocator_type; + + allocator_type root1{0},root2{0}; + rooted_poly_collection p{root1}; + const rooted_poly_collection& cp=p; + ValueFactory v; + + fill< + constraints<is_equality_comparable,is_copy_constructible>, + Types... + >(p,v,2); + + { + rooted_poly_collection p2{cp}; + BOOST_TEST(p2==p); + BOOST_TEST(p2.get_allocator().comes_from(root1)); + } + { + rooted_poly_collection p2{cp}; + auto d2=get_layout_data<Types...>(p2); + rooted_poly_collection p3{std::move(p2)}; + auto d3=get_layout_data<Types...>(p3); + BOOST_TEST(p3==p); + BOOST_TEST(d2==d3); + BOOST_TEST(p2.empty()); + do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...); + BOOST_TEST(p2.get_allocator().comes_from(root1)); + } + { + rooted_poly_collection p2{cp,root2}; + BOOST_TEST(p2==p); + BOOST_TEST(p2.get_allocator().comes_from(root2)); + } +#if BOOST_WORKAROUND(BOOST_MSVC,<=1900) + /* std::unordered_map allocator move ctor does not work when source and + * and target allocators are not equal. + */ + + if(AlwaysEqual) +#endif +#if BOOST_WORKAROUND(_MSVC_STL_UPDATE,==201811L) + /* This particular version of VS2019 has a bug in std::unordered_map + * allocator move ctor when source and target allocators are not equal. + * After private communication from Billy O'Neal. + */ + + if(AlwaysEqual) +#endif + { + rooted_poly_collection p2{cp}; + auto d2=get_layout_data<Types...>(p2); + rooted_poly_collection p3{std::move(p2),root2}; + auto d3=get_layout_data<Types...>(p3); + + BOOST_TEST(p3==p); + +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* Limitations from libstdc++-v3 force move construction with allocator + * to decay to copy construction with allocator. + */ + + (void)(d2==d3); /* Wunused-variable */ +#else + if(AlwaysEqual)BOOST_TEST(d2==d3); +#endif + + BOOST_TEST(p2.empty()); + do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...); + +#if !defined(BOOST_MSVC)&&\ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB,BOOST_TESTED_AT(804)) + /* Very odd behavior probably due to std::unordered_map allocator move + * ctor being implemented with move assignment, as reported in + * https://github.com/boostorg/poly_collection/issues/16 + */ + + if(!(Propagate&&!AlwaysEqual)) +#endif + BOOST_TEST(p3.get_allocator().comes_from(root2)); + } + { + rooted_poly_collection p2{root2}; + p2=cp; + BOOST_TEST(p2==p); + +#if BOOST_WORKAROUND(BOOST_MSVC,<=1900) + /* std::unordered_map copy assignment does not propagate allocators */ + + if(!Propagate) +#endif +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* std::unordered_map copy assignment always and only propagates unequal + * allocators. + */ + + if(!((Propagate&&AlwaysEqual)||(!Propagate&&!AlwaysEqual))) +#endif +#if !defined(BOOST_MSVC)&&\ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB,BOOST_TESTED_AT(804)) + /* std::unordered_map copy assignment does not propagate allocators, as + * reported in https://github.com/boostorg/poly_collection/issues/16 + */ + + if(!Propagate) +#endif + BOOST_TEST(p2.get_allocator().comes_from(Propagate?root1:root2)); + } +#if BOOST_WORKAROUND(BOOST_MSVC,<=1900) + /* std::unordered_map move asignment does not propagate allocators */ + + if(!Propagate&&AlwaysEqual) +#endif + { + rooted_poly_collection p2{cp}; + auto d2=get_layout_data<Types...>(p2); + rooted_poly_collection p3{root2}; + p3=std::move(p2); + auto d3=get_layout_data<Types...>(p3); + BOOST_TEST(p3==p); + if(Propagate||AlwaysEqual){ + BOOST_TEST(d2==d3); + BOOST_TEST(p2.empty()); + do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...); + } + +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* std::unordered_map move assignment always and only propagates unequal + * allocators. + */ + + if(!((Propagate&&AlwaysEqual)||(!Propagate&&!AlwaysEqual))) +#endif +#if !defined(BOOST_MSVC)&&\ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB,BOOST_TESTED_AT(804)) + /* std::unordered_map move assignment does not propagate equal allocators, + * as reported in https://github.com/boostorg/poly_collection/issues/16 + */ + + if(!(Propagate&&AlwaysEqual)) +#endif + BOOST_TEST(p3.get_allocator().comes_from(Propagate?root1:root2)); + } +#if BOOST_WORKAROUND(BOOST_MSVC,<=1900) + /* std::unordered_map::swap does not correctly swap control information when + * swapping allocators, which causes crashes on "Checked Iterators" mode. + */ + + if(!(Propagate&&!AlwaysEqual)) +#endif + { + constexpr bool use_same_allocator=!Propagate&&!AlwaysEqual; + + rooted_poly_collection p2{cp}, + p3{use_same_allocator?root1:root2}; + + auto d2=get_layout_data<Types...>(p2), + d3=get_layout_data<Types...>(p3); + + p2.swap(p3); + auto e2=get_layout_data<Types...>(p2), + e3=get_layout_data<Types...>(p3); + BOOST_TEST(d2==e3); + BOOST_TEST(d3==e2); + do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...); + if(!use_same_allocator +#if BOOST_WORKAROUND(BOOST_MSVC,<=1900) + /* std::unordered_map::swap does not swap equal allocators */ + + &&!(Propagate&&AlwaysEqual) +#endif +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* std::unordered_map::swap always and only swaps unequal allocators */ + + &&!((Propagate&&AlwaysEqual)||(!Propagate&&!AlwaysEqual)) +#endif +#if !defined(BOOST_MSVC)&&\ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB,BOOST_TESTED_AT(804)) + /* std::unordered_map::swap does not swap equal allocators, as reported + * in https://github.com/boostorg/poly_collection/issues/16 + */ + + &&!(Propagate&&AlwaysEqual) +#endif + ){ + BOOST_TEST(p2.get_allocator().comes_from(Propagate?root2:root1)); + BOOST_TEST(p3.get_allocator().comes_from(Propagate?root1:root2)); + } + + using std::swap; + swap(p2,p3); + auto f2=get_layout_data<Types...>(p2), + f3=get_layout_data<Types...>(p3); + BOOST_TEST(e2==f3); + BOOST_TEST(e3==f2); + do_((BOOST_TEST(!p3.template is_registered<Types>()),0)...); + if(!use_same_allocator){ + BOOST_TEST(p2.get_allocator().comes_from(root1)); + BOOST_TEST(p3.get_allocator().comes_from(root2)); + } + } +} + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_construction() +{ + { + constexpr bool propagate=true,always_equal=true; + + test_allocator_aware_construction< + !propagate,!always_equal,PolyCollection,ValueFactory,Types...>(); + test_allocator_aware_construction< + !propagate, always_equal,PolyCollection,ValueFactory,Types...>(); + test_allocator_aware_construction< + propagate,!always_equal,PolyCollection,ValueFactory,Types...>(); + test_allocator_aware_construction< + propagate, always_equal,PolyCollection,ValueFactory,Types...>(); + } + + { + PolyCollection p; + const PolyCollection& cp=p; + ValueFactory v; + + fill< + constraints<is_equality_comparable,is_copy_constructible>, + Types... + >(p,v,2); + + { + PolyCollection p2{cp.begin(),cp.end()}; + BOOST_TEST(p2==p); + } + { + using type=first_of< + constraints<is_equality_comparable,is_copy_constructible>, + Types...>; + + PolyCollection p2{cp.template begin<type>(),cp.template end<type>()}; + BOOST_TEST( + p2.size()==cp.template size<type>()&& + std::equal( + p2.template begin<type>(),p2.template end<type>(), + cp.template begin<type>())); + } + } + + { + using not_copy_constructible= + boost::poly_collection::not_copy_constructible; + + PolyCollection p; + const PolyCollection& cp=p; + ValueFactory v; + + fill< + constraints<is_equality_comparable,is_not_copy_constructible>, + Types... + >(p,v,2); + +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900) + /* std::unordered_map copy construction and assigment crash when elements + * throw on copy construction. + */ + + static_assert( + sizeof(not_copy_constructible)>0,""); /* Wunused-local-typedefs */ + (void)cp; /* Wunused-variable */ +#else + check_throw<not_copy_constructible>([&]{ + PolyCollection p2{cp}; + (void)p2; + }); + check_throw<not_copy_constructible>([&]{ + PolyCollection p2; + p2=cp; + }); +#endif + + { + PolyCollection p2{std::move(p)}; + BOOST_TEST(!p2.empty()); + BOOST_TEST(p.empty()); + do_((BOOST_TEST(!p.template is_registered<Types>()),0)...); + + p={std::move(p2)}; + BOOST_TEST(!p.empty()); + BOOST_TEST(p2.empty()); + do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...); + } + } +} + +void test_scoped_allocator() +{ +#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)&&\ + BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,>40704) + /* std::scoped_allocator_adaptor not assignable, see + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65279 . + * The bug prevents poly_collection below from creating any segment. + */ +#else + using vector_allocator=rooted_allocator<char>; + using vector=std::vector<char,vector_allocator>; + using concept_=boost::type_erasure::relaxed; + using element_allocator=rooted_allocator< + boost::poly_collection::any_collection_value_type<concept_> + >; + using collection_allocator=std::scoped_allocator_adaptor< + element_allocator, + vector_allocator + >; + using poly_collection= + boost::any_collection<concept_,collection_allocator>; + + element_allocator roote{0}; + vector_allocator rootv{0}; + collection_allocator al{roote,rootv}; + poly_collection p{al}; + + p.emplace<vector>(); + auto& s=*p.begin<vector>(); + BOOST_TEST(p.get_allocator().comes_from(roote)); + +#if BOOST_WORKAROUND(BOOST_MSVC,>=1910)&&BOOST_WORKAROUND(BOOST_MSVC,<1916) + /* https://developercommunity.visualstudio.com/content/problem/246251/ + * 3136309.html + */ +#else + BOOST_TEST(s.get_allocator().comes_from(rootv)); +#endif +#endif +} + +void test_construction() +{ + test_construction< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_construction< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_construction< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); + test_scoped_allocator(); +} diff --git a/src/boost/libs/poly_collection/test/test_construction.hpp b/src/boost/libs/poly_collection/test/test_construction.hpp new file mode 100644 index 00000000..4b7109e2 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_construction.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_construction(); diff --git a/src/boost/libs/poly_collection/test/test_construction_main.cpp b/src/boost/libs/poly_collection/test/test_construction_main.cpp new file mode 100644 index 00000000..a3bd4ec7 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_construction_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_construction.hpp" + +int main() +{ + test_construction(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_emplacement.cpp b/src/boost/libs/poly_collection/test/test_emplacement.cpp new file mode 100644 index 00000000..cf4acc75 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_emplacement.cpp @@ -0,0 +1,121 @@ +/* Copyright 2016 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. + */ + +#include "test_emplacement.hpp" + +#include <boost/core/lightweight_test.hpp> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_emplacement() +{ + { + using type=first_of< + constraints< + is_constructible_from_int,is_not_copy_constructible, + is_not_copy_assignable, + is_equality_comparable + >, + Types... + >; + using iterator=typename PolyCollection::iterator; + using local_base_iterator=typename PolyCollection::local_base_iterator; + using local_iterator= + typename PolyCollection::template local_iterator<type>; + + PolyCollection p; + + iterator it=p.template emplace<type>(4); + BOOST_TEST(*p.template begin<type>()==type{4}); + BOOST_TEST(&*it==&*p.begin(typeid(type))); + + iterator it2=p.template emplace_hint<type>(it,3); + BOOST_TEST(*p.template begin<type>()==type{3}); + BOOST_TEST(&*it2==&*p.begin(typeid(type))); + + iterator it3=p.template emplace_hint<type>(p.cend(),5); + BOOST_TEST(*(p.template end<type>()-1)==type{5}); + BOOST_TEST(&*it3==&*(p.end(typeid(type))-1)); + + local_base_iterator lbit= + p.template emplace_pos<type>(p.begin(typeid(type)),2); + BOOST_TEST(*static_cast<local_iterator>(lbit)==type{2}); + BOOST_TEST(lbit==p.begin(typeid(type))); + + local_base_iterator lbit2= + p.template emplace_pos<type>(p.cend(typeid(type)),6); + BOOST_TEST(*static_cast<local_iterator>(lbit2)==type{6}); + BOOST_TEST(lbit2==p.end(typeid(type))-1); + + local_iterator lit=p.emplace_pos(p.template begin<type>(),1); + BOOST_TEST(*lit==type{1}); + BOOST_TEST(lit==p.template begin<type>()); + + local_iterator lit2=p.emplace_pos(p.template cend<type>(),7); + BOOST_TEST(*lit2==type{7}); + BOOST_TEST(lit2==p.template end<type>()-1); + } + { + using type=first_of< + constraints<is_default_constructible>, + Types... + >; + + PolyCollection p; + + p.template emplace<type>(); + p.template emplace_hint<type>(p.begin()); + p.template emplace_hint<type>(p.cend()); + p.template emplace_pos<type>(p.begin(typeid(type))); + p.template emplace_pos<type>(p.cend(typeid(type))); + p.emplace_pos(p.template begin<type>()); + p.emplace_pos(p.template cend<type>()); + BOOST_TEST(p.size()==7); + } + { + using type=first_of< + constraints<is_not_copy_constructible>, + Types... + >; + + PolyCollection p; + ValueFactory v; + + p.template emplace<type>(v.template make<type>()); + p.template emplace_hint<type>(p.begin(),v.template make<type>()); + p.template emplace_hint<type>(p.cend(),v.template make<type>()); + p.template emplace_pos<type>( + p.begin(typeid(type)),v.template make<type>()); + p.template emplace_pos<type>( + p.cend(typeid(type)),v.template make<type>()); + p.emplace_pos(p.template begin<type>(),v.template make<type>()); + p.emplace_pos(p.template cend<type>(),v.template make<type>()); + BOOST_TEST(p.size()==7); + } +} + +void test_emplacement() +{ + test_emplacement< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_emplacement< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_emplacement< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_emplacement.hpp b/src/boost/libs/poly_collection/test/test_emplacement.hpp new file mode 100644 index 00000000..56cfba24 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_emplacement.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_emplacement(); diff --git a/src/boost/libs/poly_collection/test/test_emplacement_main.cpp b/src/boost/libs/poly_collection/test/test_emplacement_main.cpp new file mode 100644 index 00000000..9f29930e --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_emplacement_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_emplacement.hpp" + +int main() +{ + test_emplacement(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_erasure.cpp b/src/boost/libs/poly_collection/test/test_erasure.cpp new file mode 100644 index 00000000..45d0644a --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_erasure.cpp @@ -0,0 +1,151 @@ +/* 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. + */ + +#include "test_erasure.hpp" + +#include <boost/core/lightweight_test.hpp> +#include <iterator> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename Type,typename PolyCollection> +void test_local_erase(const PolyCollection& p2) +{ + using size_type=typename PolyCollection::size_type; + + for(size_type i=0;i<p2.template size<Type>();++i){ + PolyCollection p=p2; + auto it=p.erase(p.template cbegin<Type>()+i); + BOOST_TEST(it-p.template begin<Type>()==(std::ptrdiff_t)i); + BOOST_TEST(p.template size<Type>()==p2.template size<Type>()-1); + } +} + +template<typename Type,typename PolyCollection> +void test_local_range_erase(const PolyCollection& p2) +{ + using size_type=typename PolyCollection::size_type; + + for(size_type i=0;i<=p2.template size<Type>();++i){ + for(size_type j=i;j<=p2.template size<Type>();++j){ + PolyCollection p=p2; + auto first=p.template cbegin<Type>()+i, + last=p.template cbegin<Type>()+j; + auto it=p.erase(first,last); + BOOST_TEST(it-p.template begin<Type>()==(std::ptrdiff_t)i); + BOOST_TEST(p.template size<Type>()==p2.template size<Type>()-(j-i)); + } + } +} + +template<typename Type,typename PolyCollection> +void test_local_clear(const PolyCollection& p2) +{ + PolyCollection p=p2; + p.template clear<Type>(); + BOOST_TEST(p.template empty<Type>()); + BOOST_TEST(p.size()==p2.size()-p2.template size<Type>()); +} + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_erasure() +{ + using size_type=typename PolyCollection::size_type; + + PolyCollection p,p2; + ValueFactory v; + + fill<constraints<is_copy_constructible>,Types...>(p2,v,5); + auto sit=p2.segment_traversal().begin(); + p2.clear(sit->type_info()); + ++sit;++sit; + p2.clear(sit->type_info()); + + for(size_type i=0;i<p2.size();++i){ + p=p2; + auto it=p.erase(std::next(p.cbegin(),i)); + BOOST_TEST(std::distance(p.begin(),it)==(std::ptrdiff_t)i); + BOOST_TEST(p.size()==p2.size()-1); + } + + for(auto s:p2.segment_traversal()){ + auto& info=s.type_info(); + for(size_type i=0;i<p2.size(info);++i){ + p=p2; + auto it=p.erase(p.cbegin(info)+i); + BOOST_TEST(it-p.begin(info)==(std::ptrdiff_t)i); + BOOST_TEST(p.size(info)==p2.size(info)-1); + } + } + + do_(( + p2.template is_registered<Types>()?test_local_erase<Types>(p2),0:0)...); + + for(size_type i=0;i<=p2.size();++i){ + for(size_type j=i;j<=p2.size();++j){ + p=p2; + auto first=std::next(p.cbegin(),i), + last=std::next(p.cbegin(),j); + auto it=p.erase(first,last); + BOOST_TEST(std::distance(p.begin(),it)==(std::ptrdiff_t)i); + BOOST_TEST(p.size()==p2.size()-(j-i)); + } + } + + for(auto s:p2.segment_traversal()){ + auto& info=s.type_info(); + for(size_type i=0;i<=p2.size(info);++i){ + for(size_type j=i;j<=p2.size(info);++j){ + p=p2; + auto first=p.cbegin(info)+i, + last=p.cbegin(info)+j; + auto it=p.erase(first,last); + BOOST_TEST(it-p.begin(info)==(std::ptrdiff_t)i); + BOOST_TEST(p.size(info)==p2.size(info)-(j-i)); + } + } + } + + do_((p2.template is_registered<Types>()? + test_local_range_erase<Types>(p2),0:0)...); + + p=p2; + p.clear(); + BOOST_TEST(p.empty()); + + for(auto s:p2.segment_traversal()){ + auto& info=s.type_info(); + p=p2; + p.clear(info); + BOOST_TEST(p.empty(info)); + BOOST_TEST(p.size()==p2.size()-p2.size(info)); + } + + do_((p2.template is_registered<Types>()? + test_local_clear<Types>(p2),0:0)...); +} + +void test_erasure() +{ + test_erasure< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_erasure< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_erasure< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_erasure.hpp b/src/boost/libs/poly_collection/test/test_erasure.hpp new file mode 100644 index 00000000..68539329 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_erasure.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_erasure(); diff --git a/src/boost/libs/poly_collection/test/test_erasure_main.cpp b/src/boost/libs/poly_collection/test/test_erasure_main.cpp new file mode 100644 index 00000000..997ee1bd --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_erasure_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_erasure.hpp" + +int main() +{ + test_erasure(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_insertion.cpp b/src/boost/libs/poly_collection/test/test_insertion.cpp new file mode 100644 index 00000000..22099bbe --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_insertion.cpp @@ -0,0 +1,354 @@ +/* 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. + */ + +#include "test_insertion.hpp" + +#include <algorithm> +#include <boost/core/lightweight_test.hpp> +#include <numeric> +#include <vector> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_insertion() +{ + { + using unregistered_type=boost::poly_collection::unregistered_type; + using type=first_of<constraints<is_copy_constructible>,Types...>; + + PolyCollection p,p2; + ValueFactory v; + + p2.insert(v.template make<type>()); + check_throw<unregistered_type>( + [&]{p.insert(*p2.begin());}, + [&]{p.insert(p.end(),*p2.begin());}, + [&]{p.insert(p.cend(),*p2.begin());}, + [&]{p.insert( + external_iterator(p2.begin()),external_iterator(p2.end()));}, + [&]{p.insert( + p.end(), + external_iterator(p2.begin()),external_iterator(p2.end()));}, + [&]{p.insert( + p.cend(), + external_iterator(p2.begin()),external_iterator(p2.end()));}); + } + { + using not_copy_constructible= + boost::poly_collection::not_copy_constructible; + using type=first_of<constraints<is_not_copy_constructible>,Types...>; + + PolyCollection p,p2; + ValueFactory v; + + p.template register_types<type>(); + p2.insert(v.template make<type>()); + auto p2b=external_iterator(p2.begin()), + p2e=external_iterator(p2.end()); + auto p2lb=external_iterator(p2.template begin<type>()), + p2le=external_iterator(p2.template end<type>()); + check_throw<not_copy_constructible>( + [&]{p.insert(*p2.begin());}, + [&]{p.insert(p.end(),*p2.begin());}, + [&]{p.insert(p.cend(),*p2.cbegin());}, + [&]{p.insert(p.end(typeid(type)),*p2.begin());}, + [&]{p.insert(p.cend(typeid(type)),*p2.begin());}, + [&]{p.insert(p.template end<type>(),*p2.begin());}, + [&]{p.insert(p.template cend<type>(),*p2.begin());}, + [&]{p.insert(p2b,p2e);}, + [&]{p.insert(p2lb,p2le);}, + [&]{p.insert(p2.begin(),p2.end());}, + [&]{p.insert(p2.begin(typeid(type)),p2.end(typeid(type)));}, + [&]{p.insert(p2.template begin<type>(),p2.template end<type>());}, + [&]{p.insert(p.end(),p2b,p2e);}, + [&]{p.insert(p.end(),p2lb,p2le);}, + [&]{p.insert(p.end(),p2.begin(),p2.end());}, + [&]{p.insert(p.end(),p2.begin(typeid(type)),p2.end(typeid(type)));}, + [&]{p.insert( + p.end(),p2.template begin<type>(),p2.template end<type>());}, + [&]{p.insert(p.cend(),p2b,p2e);}, + [&]{p.insert(p.cend(),p2lb,p2le);}, + [&]{p.insert(p.cend(),p2.begin(),p2.end());}, + [&]{p.insert(p.cend(),p2.begin(typeid(type)),p2.end(typeid(type)));}, + [&]{p.insert( + p.cend(),p2.template begin<type>(),p2.template end<type>());}, + [&]{p.insert(p.end(typeid(type)),p2b,p2e);}, + [&]{p.insert(p.cend(typeid(type)),p2b,p2e);}, + [&]{p.insert(p.template end<type>(),p2b,p2e);}, + [&]{p.insert(p.template cend<type>(),p2b,p2e);}); + } + { + PolyCollection p; + ValueFactory v; + + fill<constraints<>,Types...>(p,v,2); + + do_((BOOST_TEST( + is_last( + p,typeid(Types), + p.insert(constref_if_copy_constructible(v.template make<Types>()))) + ),0)...); + } + { + PolyCollection p; + ValueFactory v; + + fill<constraints<>,Types...>(p,v,2); + + auto& info=p.segment_traversal().begin()->type_info(); + do_((BOOST_TEST( + info==typeid(Types)? + is_first( + p,typeid(Types), + p.insert( + p.cbegin(), + constref_if_copy_constructible(v.template make<Types>()))): + is_last( + p,typeid(Types), + p.insert( + p.cbegin(), + constref_if_copy_constructible(v.template make<Types>()))) + ),0)...); + + do_((BOOST_TEST( + is_first( + p,typeid(Types), + p.insert( + p.cbegin(typeid(Types)), + constref_if_copy_constructible(v.template make<Types>()))) + ),0)...); + + do_((BOOST_TEST( + is_first<Types>( + p, + p.insert( + p.template cbegin<Types>(), + constref_if_copy_constructible(v.template make<Types>()))) + ),0)...); + } + { + PolyCollection p,p2; + ValueFactory v; + + p.template register_types<Types...>(); + p2.template register_types<Types...>(); + fill< + constraints<is_copy_constructible,is_equality_comparable>, + Types... + >(p2,v,2); + + p.insert(external_iterator(p2.begin()),external_iterator(p2.end())); + BOOST_TEST(p==p2); + p.clear(); + + p.insert(p2.begin(),p2.end()); + BOOST_TEST(p==p2); + p.clear(); + + p.insert(p2.cbegin(),p2.cend()); + BOOST_TEST(p==p2); + p.clear(); + + for(auto s:p2.segment_traversal()){ + p.insert(s.begin(),s.end()); + BOOST_TEST(p.size()==p2.size(s.type_info())); + p.clear(); + + p.insert(s.cbegin(),s.cend()); + BOOST_TEST(p.size()==p2.size(s.type_info())); + p.clear(); + } + + do_(( + p.insert( + external_iterator(p2.template begin<Types>()), + external_iterator(p2.template end<Types>())), + BOOST_TEST(p.size()==p2.template size<Types>()), + p.clear() + ,0)...); + + do_(( + p.insert(p2.template begin<Types>(),p2.template end<Types>()), + BOOST_TEST(p.size()==p2.template size<Types>()), + p.clear() + ,0)...); + + do_(( + p.insert(p2.template cbegin<Types>(),p2.template cend<Types>()), + BOOST_TEST(p.size()==p2.template size<Types>()), + p.clear() + ,0)...); + } + { + PolyCollection p,p1,p2; + ValueFactory v; + + p2.template register_types<Types...>(); + fill< + constraints<is_copy_constructible,is_equality_comparable>, + Types... + >(p1,v,2); + fill< + constraints<is_copy_constructible,is_equality_comparable>, + Types... + >(p2,v,2); + + auto remove_original=[](PolyCollection& p) + { + bool first=true; + for(auto s:p.segment_traversal()){ + if(first)p.erase(s.end()-2,s.end()),first=false; + else p.erase(s.begin(),s.begin()+2); + } + }; + + p=p1; + p.insert( + p.begin(),external_iterator(p2.begin()),external_iterator(p2.end())); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + p.insert(p.begin(),p2.begin(),p2.end()); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + p.insert(p.begin(),p2.cbegin(),p2.cend()); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + for(auto s:p2.segment_traversal())p.insert(p.begin(),s.begin(),s.end()); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + for(auto s:p2.segment_traversal())p.insert(p.begin(),s.cbegin(),s.cend()); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + do_((p.insert( + p.begin(), + external_iterator(p2.template begin<Types>()), + external_iterator(p2.template end<Types>())),0)...); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + do_((p.insert( + p.begin(),p2.template begin<Types>(),p2.template end<Types>()),0)...); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + do_((p.insert( + p.begin(),p2.template cbegin<Types>(),p2.template cend<Types>()),0)...); + remove_original(p); + BOOST_TEST(p==p2); + } + { + using type=first_of< + constraints<is_copy_constructible,is_equality_comparable>, + Types... + >; + + PolyCollection p,p1,p2; + ValueFactory v; + + fill<constraints<>,type>(p1,v,2); + fill<constraints<>,type>(p2,v,2); + + auto remove_original=[](PolyCollection& p) + { + auto it=p.segment_traversal().begin()->end(); + p.erase(it-2,it); + }; + + p=p1; + BOOST_TEST(is_first( + p,typeid(type), + p.insert( + p.begin(typeid(type)), + external_iterator(p2.begin()),external_iterator(p2.end())))); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + BOOST_TEST(is_first( + p,typeid(type), + p.insert( + p.cbegin(typeid(type)), + external_iterator(p2.begin()),external_iterator(p2.end())))); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + BOOST_TEST(is_first<type>( + p, + p.insert( + p.template begin<type>(), + external_iterator(p2.begin()),external_iterator(p2.end())))); + remove_original(p); + BOOST_TEST(p==p2); + + p=p1; + BOOST_TEST(is_first<type>( + p, + p.insert( + p.template cbegin<type>(), + external_iterator(p2.begin()),external_iterator(p2.end())))); + remove_original(p); + BOOST_TEST(p==p2); + } + { + using type=first_of< + constraints< + is_constructible_from_int,is_not_copy_constructible, + is_equality_comparable + >, + Types... + >; + + PolyCollection p; + std::vector<int> s(10); + ValueFactory v; + + fill<constraints<>,type>(p,v,2); + std::iota(s.begin(),s.end(),0); + BOOST_TEST(is_first<type>( + p, + p.insert(p.template begin<type>(),s.begin(),s.end()))); + BOOST_TEST( + std::equal(s.begin(),s.end(),p.template begin<type>(), + [](int x,const type& y){return type{x}==y;}) + ); + } +} + +void test_insertion() +{ + test_insertion< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_insertion< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_insertion< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_insertion.hpp b/src/boost/libs/poly_collection/test/test_insertion.hpp new file mode 100644 index 00000000..920a7a41 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_insertion.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_insertion(); diff --git a/src/boost/libs/poly_collection/test/test_insertion_main.cpp b/src/boost/libs/poly_collection/test/test_insertion_main.cpp new file mode 100644 index 00000000..999158fd --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_insertion_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_insertion.hpp" + +int main() +{ + test_insertion(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_iterators.cpp b/src/boost/libs/poly_collection/test/test_iterators.cpp new file mode 100644 index 00000000..98ccfaa4 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_iterators.cpp @@ -0,0 +1,310 @@ +/* Copyright 2016-2018 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. + */ + +#include "test_iterators.hpp" + +#include <boost/core/lightweight_test.hpp> +#include <iterator> +#include <type_traits> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename Iterator> +using is_input=std::is_base_of< + std::input_iterator_tag, + typename std::iterator_traits<Iterator>::iterator_category +>; +template<typename Iterator> +using is_forward=std::is_base_of< + std::forward_iterator_tag, + typename std::iterator_traits<Iterator>::iterator_category +>; +template<typename Iterator> +using is_random_access=std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits<Iterator>::iterator_category +>; + +template<typename Type,typename PolyCollection> +void test_iterators(PolyCollection& p) +{ + using local_base_iterator=typename PolyCollection::local_base_iterator; + using const_local_base_iterator= + typename PolyCollection::const_local_base_iterator; + using local_iterator=typename PolyCollection::template local_iterator<Type>; + using const_local_iterator= + typename PolyCollection::template const_local_iterator<Type>; + using base_segment_info=typename PolyCollection::base_segment_info; + using const_base_segment_info= + typename PolyCollection::const_base_segment_info; + using const_segment_info= + typename PolyCollection::template const_segment_info<Type>; + using segment_info=typename PolyCollection::template segment_info<Type>; + + static_assert(is_random_access<local_iterator>::value, + "local_iterator must be random access"); + static_assert(is_random_access<const_local_iterator>::value, + "const_local_iterator must be random access"); + static_assert(std::is_base_of<const_segment_info,segment_info>::value, + "segment_info must derive from const_segment_info"); + + { + local_iterator lit,lit2; + const_local_iterator clit,clit2(lit); /* sorry about the names */ + + lit=lit2; + clit=clit2; + clit=lit; + } + + const PolyCollection& cp=p; + std::size_t n=0; + local_base_iterator lbfirst=p.begin(typeid(Type)), + lblast=p.end(typeid(Type)); + const_local_base_iterator clbfirst=cp.begin(typeid(Type)), + clblast=cp.end(typeid(Type)); + local_iterator lfirst=p.template begin<Type>(), + llast=p.template end<Type>(); + const_local_iterator clfirst=cp.template begin<Type>(), + cllast=cp.template end<Type>(); + base_segment_info bi=p.segment(typeid(Type)); + const_base_segment_info cbi=cp.segment(typeid(Type)); + segment_info i=p.template segment<Type>(); + const_segment_info ci=cp.template segment<Type>(); + + BOOST_TEST(clbfirst==cp.cbegin(typeid(Type))); + BOOST_TEST(clblast==cp.cend(typeid(Type))); + BOOST_TEST(clfirst==cp.template cbegin<Type>()); + BOOST_TEST(cllast==cp.template cend<Type>()); + + BOOST_TEST(lbfirst==bi.begin()); + BOOST_TEST(lblast==bi.end()); + BOOST_TEST(clbfirst==bi.cbegin()); + BOOST_TEST(clbfirst==cbi.begin()); + BOOST_TEST(clblast==bi.cend()); + BOOST_TEST(clblast==cbi.end()); + + BOOST_TEST(lfirst==i.begin()); + BOOST_TEST(llast==i.end()); + BOOST_TEST(clfirst==i.cbegin()); + BOOST_TEST(clfirst==ci.begin()); + BOOST_TEST(cllast==i.cend()); + BOOST_TEST(cllast==ci.end()); + + for(;lbfirst!=lblast;++lbfirst,++clbfirst,++lfirst,++clfirst){ + BOOST_TEST(lfirst==static_cast<local_iterator>(lbfirst)); + BOOST_TEST(static_cast<local_base_iterator>(lfirst)==lbfirst); + BOOST_TEST(clfirst==static_cast<const_local_iterator>(clbfirst)); + BOOST_TEST(static_cast<const_local_base_iterator>(clfirst)==clbfirst); + BOOST_TEST(clfirst==lfirst); + BOOST_TEST(&*lfirst==&*static_cast<local_iterator>(lbfirst)); + BOOST_TEST(&*clfirst==&*static_cast<const_local_iterator>(clbfirst)); + BOOST_TEST(&*clfirst==&*lfirst); + + Type& r=p.template begin<Type>()[n]; + const Type& cr=cp.template begin<Type>()[n]; + + BOOST_TEST(&*lfirst==&r); + BOOST_TEST(&*clfirst==&cr); + + ++n; + } + BOOST_TEST(clbfirst==clblast); + BOOST_TEST(lfirst==llast); + BOOST_TEST(clfirst==cllast); + BOOST_TEST(lfirst==static_cast<local_iterator>(llast)); + BOOST_TEST(clfirst==static_cast<const_local_iterator>(cllast)); + BOOST_TEST(clfirst==llast); + BOOST_TEST((std::ptrdiff_t)n==p.end(typeid(Type))-p.begin(typeid(Type))); + BOOST_TEST( + (std::ptrdiff_t)n==p.template end<Type>()-p.template begin<Type>()); + + for(auto s:p.segment_traversal()){ + if(s.type_info()==typeid(Type)){ + const auto& cs=s; + + BOOST_TEST( + s.template begin<Type>()== + static_cast<local_iterator>(s.begin())); + BOOST_TEST( + s.template end<Type>()== + static_cast<local_iterator>(s.end())); + BOOST_TEST( + cs.template begin<Type>()== + static_cast<const_local_iterator>(cs.begin())); + BOOST_TEST( + cs.template end<Type>()== + static_cast<const_local_iterator>(cs.end())); + BOOST_TEST( + cs.template cbegin<Type>()== + static_cast<const_local_iterator>(cs.cbegin())); + BOOST_TEST( + cs.template cend<Type>()== + static_cast<const_local_iterator>(cs.cend())); + } + } +} + +template<typename PolyCollection,typename ValueFactory,typename... Types> +void test_iterators() +{ + using value_type=typename PolyCollection::value_type; + using iterator=typename PolyCollection::iterator; + using const_iterator=typename PolyCollection::const_iterator; + using local_base_iterator=typename PolyCollection::local_base_iterator; + using const_local_base_iterator= + typename PolyCollection::const_local_base_iterator; + using const_base_segment_info= + typename PolyCollection::const_base_segment_info; + using base_segment_info=typename PolyCollection::base_segment_info; + using base_segment_info_iterator= + typename PolyCollection::base_segment_info_iterator; + using const_base_segment_info_iterator= + typename PolyCollection::const_base_segment_info_iterator; + using const_segment_traversal_info= + typename PolyCollection::const_segment_traversal_info; + using segment_traversal_info= + typename PolyCollection::segment_traversal_info; + + static_assert(is_forward<iterator>::value, + "iterator must be forward"); + static_assert(is_forward<const_iterator>::value, + "const_iterator must be forward"); + static_assert(is_random_access<local_base_iterator>::value, + "local_base_iterator must be random access"); + static_assert(is_random_access<const_local_base_iterator>::value, + "const_local_base_iterator must be random access"); + static_assert(std::is_base_of< + const_base_segment_info,base_segment_info>::value, + "base_segment_info must derive from const_base_segment_info"); + static_assert(is_input<base_segment_info_iterator>::value, + "base_segment_info_iterator must be input"); + static_assert(is_input<const_base_segment_info_iterator>::value, + "const_base_segment_info_iterator must be input"); + static_assert(std::is_base_of< + const_segment_traversal_info,segment_traversal_info>::value, + "const_segment_traversal_info must derive "\ + "from segment_traversal_info"); + + { + iterator it,it2; + const_iterator cit,cit2(it); + local_base_iterator lbit,lbit2; + const_local_base_iterator clbit,clbit2(lbit); + base_segment_info_iterator sit,sit2; + const_base_segment_info_iterator csit,csit2(csit); + + it=it2; + cit=cit2; + cit=it; + lbit=lbit2; + clbit=clbit2; + clbit=lbit; + sit=sit2; + csit=csit2; + csit=sit; + } + + PolyCollection p; + const PolyCollection& cp=p; + ValueFactory v; + + fill<constraints<>,Types...>(p,v,2); + + { + std::size_t n=0; + iterator first=p.begin(),last=p.end(); + const_iterator cfirst=cp.begin(),clast=cp.end(); + + BOOST_TEST(cfirst==cp.cbegin()); + BOOST_TEST(clast==cp.cend()); + + for(;first!=last;++first,++cfirst){ + BOOST_TEST(first==cfirst); + BOOST_TEST(&*first==&*cfirst); + + ++n; + } + BOOST_TEST(cfirst==clast); + BOOST_TEST(last==clast); + BOOST_TEST(n==p.size()); + } + + { + std::size_t n=0; + base_segment_info_iterator first=p.segment_traversal().begin(), + last=p.segment_traversal().end(); + const_base_segment_info_iterator cfirst=cp.segment_traversal().begin(), + clast=cp.segment_traversal().end(); + + BOOST_TEST(cfirst==cp.segment_traversal().cbegin()); + BOOST_TEST(clast==cp.segment_traversal().cend()); + + for(;first!=last;++first,++cfirst){ + BOOST_TEST(first==cfirst); + + std::size_t m=0; + local_base_iterator lbfirst=first->begin(),lblast=first->end(); + const_local_base_iterator clbfirst=cfirst->begin(),clblast=cfirst->end(); + + BOOST_TEST(clbfirst==cfirst->cbegin()); + BOOST_TEST(clblast==cfirst->cend()); + BOOST_TEST(lbfirst==p.begin(first->type_info())); + BOOST_TEST(lblast==p.end(first->type_info())); + BOOST_TEST(clbfirst==cp.begin(first->type_info())); + BOOST_TEST(clblast==cp.end(first->type_info())); + BOOST_TEST(clbfirst==cp.cbegin(first->type_info())); + BOOST_TEST(clblast==cp.cend(first->type_info())); + + for(;lbfirst!=lblast;++lbfirst,++clbfirst){ + BOOST_TEST(lbfirst==clbfirst); + BOOST_TEST(&*lbfirst==&*clbfirst); + + value_type& r=first->begin()[m]; + const value_type& cr=cfirst->begin()[m]; + + BOOST_TEST(&*lbfirst==&r); + BOOST_TEST(&*clbfirst==&cr); + + ++m; + } + BOOST_TEST(clbfirst==clblast); + BOOST_TEST(lblast==clblast); + BOOST_TEST((std::ptrdiff_t)m==first->end()-first->begin()); + BOOST_TEST((std::ptrdiff_t)m==cfirst->end()-cfirst->begin()); + BOOST_TEST((std::ptrdiff_t)m==cfirst->cend()-cfirst->cbegin()); + + n+=m; + } + BOOST_TEST(cfirst==clast); + BOOST_TEST(last==clast); + BOOST_TEST(n==p.size()); + } + + do_((test_iterators<Types>(p),0)...); +} + +void test_iterators() +{ + test_iterators< + any_types::collection,auto_increment, + any_types::t1,any_types::t2,any_types::t3, + any_types::t4,any_types::t5>(); + test_iterators< + base_types::collection,auto_increment, + base_types::t1,base_types::t2,base_types::t3, + base_types::t4,base_types::t5>(); + test_iterators< + function_types::collection,auto_increment, + function_types::t1,function_types::t2,function_types::t3, + function_types::t4,function_types::t5>(); +} diff --git a/src/boost/libs/poly_collection/test/test_iterators.hpp b/src/boost/libs/poly_collection/test/test_iterators.hpp new file mode 100644 index 00000000..8a2cae90 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_iterators.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_iterators(); diff --git a/src/boost/libs/poly_collection/test/test_iterators_main.cpp b/src/boost/libs/poly_collection/test/test_iterators_main.cpp new file mode 100644 index 00000000..e8bd1204 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_iterators_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_iterators.hpp" + +int main() +{ + test_iterators(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_registration.cpp b/src/boost/libs/poly_collection/test/test_registration.cpp new file mode 100644 index 00000000..05e439d6 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_registration.cpp @@ -0,0 +1,119 @@ +/* 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. + */ + +#include "test_registration.hpp" + +#include <boost/core/lightweight_test.hpp> +#include <iterator> +#include "any_types.hpp" +#include "base_types.hpp" +#include "function_types.hpp" +#include "test_utilities.hpp" + +using namespace test_utilities; + +template<typename PolyCollection,typename Type> +void test_registration() +{ + using unregistered_type=boost::poly_collection::unregistered_type; + + { + PolyCollection p; + const PolyCollection& cp=p; + + BOOST_TEST(!p.is_registered(typeid(Type))); + BOOST_TEST(!p.template is_registered<Type>()); + check_throw<unregistered_type>( + [&]{(void)p.begin(typeid(Type));}, + [&]{(void)p.end(typeid(Type));}, + [&]{(void)cp.begin(typeid(Type));}, + [&]{(void)cp.end(typeid(Type));}, + [&]{(void)p.cbegin(typeid(Type));}, + [&]{(void)p.cend(typeid(Type));}, + [&]{(void)p.template begin<Type>();}, + [&]{(void)p.template end<Type>();}, + [&]{(void)cp.template begin<Type>();}, + [&]{(void)cp.template end<Type>();}, + [&]{(void)p.template cbegin<Type>();}, + [&]{(void)p.template cend<Type>();}, + [&]{(void)p.segment(typeid(Type));}, + [&]{(void)cp.segment(typeid(Type));}, + [&]{(void)p.template segment<Type>();}, + [&]{(void)cp.template segment<Type>();}, + [&]{(void)cp.empty(typeid(Type));}, + [&]{(void)cp.size(typeid(Type));}, + [&]{(void)cp.max_size(typeid(Type));}, + [&]{(void)p.reserve(typeid(Type),0);}, + [&]{(void)cp.capacity(typeid(Type));}, + [&]{(void)p.shrink_to_fit(typeid(Type));}, + [&]{(void)p.clear(typeid(Type));}, + [&]{(void)cp.template empty<Type>();}, + [&]{(void)cp.template size<Type>();}, + [&]{(void)cp.template max_size<Type>();}, + /* reserve<Type> omitted as it actually registers the type */ + [&]{(void)cp.template capacity<Type>();}, + [&]{(void)p.template shrink_to_fit<Type>();}, + [&]{(void)p.template clear<Type>();}); + + p.register_types(); + p.template register_types<>(); + BOOST_TEST(!p.is_registered(typeid(Type))); + + p.template register_types<Type>(); + + BOOST_TEST(p.is_registered(typeid(Type))); + BOOST_TEST(p.template is_registered<Type>()); + (void)p.end(typeid(Type)); + (void)cp.begin(typeid(Type)); + (void)cp.end(typeid(Type)); + (void)p.cbegin(typeid(Type)); + (void)p.cend(typeid(Type)); + (void)p.template begin<Type>(); + (void)p.template end<Type>(); + (void)cp.template begin<Type>(); + (void)cp.template end<Type>(); + (void)cp.template cbegin<Type>(); + (void)cp.template cend<Type>(); + (void)cp.empty(typeid(Type)); + (void)cp.size(typeid(Type)); + (void)cp.max_size(typeid(Type)); + (void)p.reserve(typeid(Type),0); + (void)cp.capacity(typeid(Type)); + (void)p.shrink_to_fit(typeid(Type)); + (void)p.clear(typeid(Type)); + (void)cp.template empty<Type>(); + (void)cp.template size<Type>(); + (void)cp.template max_size<Type>(); + /* reserve<Type> omitted */ + (void)cp.template capacity<Type>(); + (void)p.template shrink_to_fit<Type>(); + (void)p.template clear<Type>(); + } + + { + PolyCollection p; + p.template reserve<Type>(0); + BOOST_TEST(p.is_registered(typeid(Type))); + } + + { + PolyCollection p; + p.template register_types<Type,Type,Type>(); + BOOST_TEST(p.is_registered(typeid(Type))); + BOOST_TEST( + std::distance( + p.segment_traversal().begin(),p.segment_traversal().end())==1); + } +} + +void test_registration() +{ + test_registration<any_types::collection,any_types::t1>(); + test_registration<base_types::collection,base_types::t1>(); + test_registration<function_types::collection,function_types::t1>(); +} diff --git a/src/boost/libs/poly_collection/test/test_registration.hpp b/src/boost/libs/poly_collection/test/test_registration.hpp new file mode 100644 index 00000000..0c927fd1 --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_registration.hpp @@ -0,0 +1,9 @@ +/* Copyright 2016 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. + */ + +void test_registration(); diff --git a/src/boost/libs/poly_collection/test/test_registration_main.cpp b/src/boost/libs/poly_collection/test/test_registration_main.cpp new file mode 100644 index 00000000..0b6ab5fc --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_registration_main.cpp @@ -0,0 +1,16 @@ +/* Copyright 2016 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. + */ + +#include <boost/core/lightweight_test.hpp> +#include "test_registration.hpp" + +int main() +{ + test_registration(); + return boost::report_errors(); +} diff --git a/src/boost/libs/poly_collection/test/test_utilities.hpp b/src/boost/libs/poly_collection/test/test_utilities.hpp new file mode 100644 index 00000000..e09f9dca --- /dev/null +++ b/src/boost/libs/poly_collection/test/test_utilities.hpp @@ -0,0 +1,410 @@ +/* Copyright 2016-2018 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_TEST_TEST_UTILITIES_HPP +#define BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <array> +#include <boost/core/lightweight_test.hpp> +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/type_traits/has_equal_to.hpp> +#include <iterator> +#include <memory> +#include <type_traits> +#include <typeinfo> +#include <utility> + +namespace test_utilities{ + +template<typename... Values> +void do_(Values...){} + +template<typename Exception,typename F> +void check_throw_case(F f) +{ + try{ + (void)f(); + BOOST_TEST(false); + } + catch(const Exception&){} + catch(...){BOOST_TEST(false);} +} + +template<typename Exception,typename... Fs> +void check_throw(Fs... f) +{ + do_((check_throw_case<Exception>(f),0)...); +} + +template<typename F1,typename F2> +struct compose_class +{ + F1 f1; + F2 f2; + + compose_class(const F1& f1,const F2& f2):f1(f1),f2(f2){} + + template<typename T,typename... Args> + auto operator()(T&& x,Args&&... args) + ->decltype(std::declval<F2>()(std::declval<F1>()( + std::forward<T>(x)),std::forward<Args>(args)...)) + { + return f2(f1(std::forward<T>(x)),std::forward<Args>(args)...); + } +}; + +template<typename F1,typename F2> +compose_class<F1,F2> compose(F1 f1,F2 f2) +{ + return {f1,f2}; +} + +template<typename F1,typename F2> +struct compose_all_class +{ + F1 f1; + F2 f2; + + compose_all_class(const F1& f1,const F2& f2):f1(f1),f2(f2){} + + template<typename... Args> + auto operator()(Args&&... args) + ->decltype(std::declval<F2>()(std::declval<F1>()( + std::forward<Args>(args))...)) + { + return f2(f1(std::forward<Args>(args))...); + } +}; + +template<typename F1,typename F2> +compose_all_class<F1,F2> compose_all(F1 f1,F2 f2) +{ + return {f1,f2}; +} + +using std::is_default_constructible; + +using std::is_copy_constructible; + +template<typename T> +using is_not_copy_constructible=std::integral_constant< + bool, + !std::is_copy_constructible<T>::value +>; + +template<typename T> +using is_constructible_from_int=std::is_constructible<T,int>; + +using std::is_copy_assignable; + +template<typename T> +using is_not_copy_assignable=std::integral_constant< + bool, + !std::is_copy_assignable<T>::value +>; + +template<typename T> +using is_equality_comparable=std::integral_constant< + bool, + boost::has_equal_to<T,T,bool>::value +>; + +template<typename T> +using is_not_equality_comparable=std::integral_constant< + bool, + !is_equality_comparable<T>::value +>; + +template< + typename T, + typename std::enable_if<is_not_copy_constructible<T>::value>::type* =nullptr +> +typename std::remove_reference<T>::type&& constref_if_copy_constructible(T&& x) +{ + return std::move(x); +} + +template< + typename T, + typename std::enable_if<is_copy_constructible<T>::value>::type* =nullptr +> +const T& constref_if_copy_constructible(T&& x) +{ + return x; +} + +template<template<typename> class... Traits> +struct constraints; + +template<> +struct constraints<> +{ + template<typename T> + struct apply:std::true_type{}; +}; + +template< + template <typename> class Trait, + template <typename> class... Traits +> +struct constraints<Trait,Traits...> +{ + template<typename T> + struct apply:std::integral_constant< + bool, + Trait<T>::value&&constraints<Traits...>::template apply<T>::value + >{}; +}; + +template<typename... Ts>struct type_list{}; + +template< + typename Constraints,template <typename...> class Template, + typename TypeList, + typename... Ts +> +struct instantiate_with_class; + +template< + typename Constraints,template <typename...> class Template, + typename... Us +> +struct instantiate_with_class<Constraints,Template,type_list<Us...>> +{using type=Template<Us...>;}; + +template< + typename Constraints,template <typename...> class Template, + typename... Us, + typename T,typename... Ts +> +struct instantiate_with_class< + Constraints,Template,type_list<Us...>,T,Ts... +>:instantiate_with_class< + Constraints,Template, + typename std::conditional< + Constraints::template apply<T>::value, + type_list<Us...,T>, + type_list<Us...> + >::type, + Ts... +>{}; + +template< + typename Constraints,template <typename...> class Template, + typename... Ts +> +using instantiate_with=typename instantiate_with_class< + Constraints,Template,type_list<>,Ts... +>::type; + +template< + template <typename...> class Template,typename... Ts +> +using only_eq_comparable=instantiate_with< + constraints<is_equality_comparable>, + Template, Ts... +>; + +template<typename T> struct identity{using type=T;}; + +template<typename Constraints,typename... Ts> +struct first_of_class{}; + +template<typename Constraints,typename T,typename... Ts> +struct first_of_class<Constraints,T,Ts...>:std::conditional< + Constraints::template apply<T>::value, + identity<T>, + first_of_class<Constraints,Ts...> +>::type{}; + +template<typename Constraints,typename... Ts> +using first_of=typename first_of_class<Constraints,Ts...>::type; + +template< + typename Constraints,typename... Ts, + typename PolyCollection,typename ValueFactory +> +void fill(PolyCollection& p,ValueFactory& v,int n) +{ + for(int i=0;i<n;++i){ + do_( + (Constraints::template apply<Ts>::value? + (p.insert(v.template make<Ts>()),0):0)...); + } +} + +template<typename PolyCollection> +bool is_first( + const PolyCollection& p,typename PolyCollection::const_iterator it) +{ + return it==p.begin(); +} + +template<typename PolyCollection,typename Iterator> +bool is_first(const PolyCollection& p,const std::type_info& info,Iterator it) +{ + return &*it==&*p.begin(info); +} + +template<typename PolyCollection,typename Iterator> +bool is_last(const PolyCollection& p,const std::type_info& info,Iterator it) +{ + return &*it==&*(p.end(info)-1); +} + +template<typename T,typename PolyCollection,typename Iterator> +bool is_first(const PolyCollection& p,Iterator it) +{ + return &*it==&*p.template begin<T>(); +} + +template<typename T,typename PolyCollection,typename Iterator> +bool is_last(const PolyCollection& p,Iterator it) +{ + return &*it==&*(p.template end<T>()-1); +} + +template<typename Iterator> +struct external_iterator_class: + public boost::iterator_adaptor<external_iterator_class<Iterator>,Iterator> +{ + external_iterator_class(const Iterator& it): + external_iterator_class::iterator_adaptor_{it}{} +}; + +template<typename Iterator> +external_iterator_class<Iterator> external_iterator(Iterator it) +{ + return it; +} + +template<typename Iterator> +struct unwrap_iterator_class:public boost::iterator_adaptor< + unwrap_iterator_class<Iterator>, + Iterator, + typename std::iterator_traits<Iterator>::value_type::type +> +{ + unwrap_iterator_class(const Iterator& it): + unwrap_iterator_class::iterator_adaptor_{it}{} +}; + +template<typename Iterator> +unwrap_iterator_class<Iterator> unwrap_iterator(Iterator it) +{ + return it; +} + +struct auto_increment +{ + template<typename T> + T make(){return T(n++);} + + int n=0; +}; + +struct jammed_auto_increment +{ + template<typename T> + T make(){return T(n++/7);} + + int n=0; +}; + +template< + typename T, + typename Propagate=std::true_type,typename AlwaysEqual=std::true_type +> +struct rooted_allocator:std::allocator<T> +{ + using propagate_on_container_copy_assignment=Propagate; + using propagate_on_container_move_assignment=Propagate; + using propagate_on_container_swap=Propagate; + using is_always_equal=AlwaysEqual; /* for C++17 forward compatibility */ + template<typename U> + struct rebind{using other=rooted_allocator<U,Propagate,AlwaysEqual>;}; + + rooted_allocator():root{nullptr}{} + explicit rooted_allocator(int):root{this}{} + template<typename U> + rooted_allocator(const rooted_allocator<U,Propagate,AlwaysEqual>& x): + root{x.root}{} + + template<typename U> + bool operator==(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return AlwaysEqual::value?true:root==x.root;} + template<typename U> + bool operator!=(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return AlwaysEqual::value?false:root!=x.root;} + + template<typename U> + bool comes_from(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return root==&x;} + +private: + template<typename,typename,typename> friend struct rooted_allocator; + + const void* root; +}; + +template< + typename PolyCollection, + template<typename...> class Allocator,typename... Args +> +struct realloc_poly_collection_class; + +template< + typename PolyCollection, + template<typename...> class Allocator,typename... Args +> +using realloc_poly_collection=typename realloc_poly_collection_class< + PolyCollection,Allocator,Args...>::type; + +template< + template<typename,typename> class PolyCollection, + typename T,typename OriginalAllocator, + template<typename...> class Allocator,typename... Args +> +struct realloc_poly_collection_class< + PolyCollection<T,OriginalAllocator>,Allocator,Args... +> +{ + using value_type=typename PolyCollection<T,OriginalAllocator>::value_type; + using type=PolyCollection<T,Allocator<value_type,Args...>>; +}; + +template<std::size_t N> +struct layout_data +{ + std::array<const void*,N> datas; + std::array<std::size_t,N> sizes; + + bool operator==(const layout_data& x)const + { + return datas==x.datas&&sizes==x.sizes; + } +}; + +template<typename... Types,typename PolyCollection> +layout_data<sizeof...(Types)> get_layout_data(const PolyCollection& p) +{ + return{ + {{(p.template is_registered<Types>()? + &*p.template begin<Types>():nullptr)...}}, + {{(p.template is_registered<Types>()? + p.template size<Types>():0)...}} + }; +} + +} /* namespace test_utilities */ + +#endif diff --git a/src/boost/libs/poly_collection/test_results.svg b/src/boost/libs/poly_collection/test_results.svg new file mode 100644 index 00000000..d3d613ff --- /dev/null +++ b/src/boost/libs/poly_collection/test_results.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> + <stop offset="1" stop-opacity=".1"/> + </linearGradient> + <clipPath id="a"> + <rect width="95" height="20" rx="3" fill="#fff"/> + </clipPath> + <g clip-path="url(#a)"> + <path fill="#555" d="M0 0h48v20H0z"/> + <path fill="#4c1" d="M48 0h47v20H48z"/> + <path fill="url(#b)" d="M0 0h95v20H0z"/> + </g> + <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> + <path fill="#fff" d="M 10.8566 9.70598 l -3.60307 0 l -0.0903426 0.15447 l -1.63598 2.79514 l -0.0919027 0.156812 l 0.0912783 0.157278 l 1.63599 2.82198 l 0.0901858 0.155564 l 3.60291 0 l 0.090498 -0.153378 l 1.64956 -2.79498 l 0.093151 -0.157907 l -0.0923709 -0.158212 l -1.64956 -2.82213 l -0.0903415 -0.154627 z m -5.06008 3.1072 l 1.63598 -2.79514 l 3.24498 0 l 1.64956 2.82213 l -1.64956 2.79498 l -3.24498 0 l -1.63598 -2.82198 z"/> + <path fill="#fff" d="M 16.6973 6.54947 l -3.6026 0 l -0.090185 0.155562 l -1.54689 2.67 l -0.0906544 0.156655 l 0.0908101 0.1565 l 1.72508 2.97067 l 0.0908101 0.156188 l 0.180528 -0.000780746 l 3.06679 -0.0137328 l 0.178187 -0.000780746 l 0.0898736 -0.153845 l 1.65658 -2.83383 l 0.0926823 -0.158528 l -0.093773 -0.15806 l -1.65658 -2.79311 l -0.0906529 -0.15291 z m -4.96959 2.98206 l 1.54689 -2.67 l 3.24498 0 l 1.65658 2.79311 l -1.65658 2.83383 l -3.06679 0.0137328 l -1.72508 -2.97067 z"/> + <path fill="#fff" d="M 12.4576 4.03269 l -3.56874 0 l -0.0898744 0.156967 l -1.61336 2.81683 l -0.0875335 0.152755 l 0.0855053 0.153848 l 0.991265 1.78437 l 0.0887818 0.160088 l 0.183024 0.000468606 l 2.38603 0.00686454 l 0.178812 0.000468606 l 0.0909666 -0.154003 l 1.72804 -2.92995 l 0.850837 0 l -0.265721 -0.466534 l -0.868311 -1.52458 l -0.0897187 -0.15759 z m -5.00126 3.12889 l 1.61336 -2.81683 l 3.20644 0 l 0.868313 1.52458 l -0.492278 0 l -1.81854 3.08348 l -2.38603 -0.00686454 l -0.991265 -1.78437 z"/> + <path fill="#cccccc" d="M 10.8566 9.70598 m -5.06008 3.1072 l 1.63598 -2.79514 l 3.24498 0 l 1.64956 2.82213 l -1.64956 2.79498 l -3.24498 0 l -1.63598 -2.82198 z"/> + <path fill="#cccccc" d="M 16.6973 6.54947 m -4.96959 2.98206 l 1.54689 -2.67 l 3.24498 0 l 1.65658 2.79311 l -1.65658 2.83383 l -3.06679 0.0137328 l -1.72508 -2.97067 z"/> + <path fill="#cccccc" d="M 12.4576 4.03269 m -5.00126 3.12889 l 1.61336 -2.81683 l 3.20644 0 l 0.868313 1.52458 l -0.492278 0 l -1.81854 3.08348 l -2.38603 -0.00686454 l -0.991265 -1.78437 z"/> + <text x="335" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">test</text> + <text x="335" y="140" transform="scale(.1)" textLength="210">test</text> + <text x="705" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">results</text> + <text x="705" y="140" transform="scale(.1)" textLength="370">results</text> + </g> +</svg>
\ No newline at end of file |