summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/poly_collection
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/poly_collection
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/poly_collection')
-rw-r--r--src/boost/libs/poly_collection/README.md33
-rw-r--r--src/boost/libs/poly_collection/example/Jamfile.v249
-rw-r--r--src/boost/libs/poly_collection/example/algorithms.cpp171
-rw-r--r--src/boost/libs/poly_collection/example/basic_any.cpp73
-rw-r--r--src/boost/libs/poly_collection/example/basic_base.cpp59
-rw-r--r--src/boost/libs/poly_collection/example/basic_function.cpp103
-rw-r--r--src/boost/libs/poly_collection/example/exceptions.cpp62
-rw-r--r--src/boost/libs/poly_collection/example/insertion_emplacement.cpp109
-rw-r--r--src/boost/libs/poly_collection/example/perf.cpp604
-rw-r--r--src/boost/libs/poly_collection/example/rolegame.hpp78
-rw-r--r--src/boost/libs/poly_collection/example/segmented_structure.cpp181
-rw-r--r--src/boost/libs/poly_collection/index.html20
-rw-r--r--src/boost/libs/poly_collection/meta/explicit-failures-markup.xml51
-rw-r--r--src/boost/libs/poly_collection/meta/libraries.json14
-rw-r--r--src/boost/libs/poly_collection/test/Jamfile.v243
-rw-r--r--src/boost/libs/poly_collection/test/any_types.hpp94
-rw-r--r--src/boost/libs/poly_collection/test/base_types.hpp92
-rw-r--r--src/boost/libs/poly_collection/test/function_types.hpp144
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm.cpp21
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm1.cpp20
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm1.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm2.cpp20
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm2.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm3.cpp20
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm3.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm_impl.hpp1122
-rw-r--r--src/boost/libs/poly_collection/test/test_algorithm_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_all_main.cpp33
-rw-r--r--src/boost/libs/poly_collection/test/test_capacity.cpp92
-rw-r--r--src/boost/libs/poly_collection/test/test_capacity.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_capacity_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_comparison.cpp173
-rw-r--r--src/boost/libs/poly_collection/test/test_comparison.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_comparison_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_construction.cpp384
-rw-r--r--src/boost/libs/poly_collection/test/test_construction.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_construction_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_emplacement.cpp121
-rw-r--r--src/boost/libs/poly_collection/test/test_emplacement.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_emplacement_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_erasure.cpp151
-rw-r--r--src/boost/libs/poly_collection/test/test_erasure.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_erasure_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_insertion.cpp354
-rw-r--r--src/boost/libs/poly_collection/test/test_insertion.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_insertion_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_iterators.cpp310
-rw-r--r--src/boost/libs/poly_collection/test/test_iterators.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_iterators_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_registration.cpp119
-rw-r--r--src/boost/libs/poly_collection/test/test_registration.hpp9
-rw-r--r--src/boost/libs/poly_collection/test/test_registration_main.cpp16
-rw-r--r--src/boost/libs/poly_collection/test/test_utilities.hpp410
-rw-r--r--src/boost/libs/poly_collection/test_results.svg26
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&#237;n M L&#243;pez Mu&#241;oz" date="18 Jun 2017">
+ Compiler's too old for working.
+ </note>
+ </mark-unusable>
+ <mark-unusable>
+ <toolset name="*98"/>
+ <note author="Joaqu&#237;n M L&#243;pez Mu&#241;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