summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/poly_collection/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/poly_collection/test
parentInitial commit. (diff)
downloadceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz
ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/poly_collection/test')
-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.cpp375
-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
40 files changed, 3966 insertions, 0 deletions
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 000000000..059e780df
--- /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 000000000..0373f058c
--- /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 000000000..fcfcb0f68
--- /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 000000000..f8c154ff1
--- /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 000000000..118c96ffd
--- /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 000000000..c687deb08
--- /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 000000000..12e0762d0
--- /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 000000000..ae9ddd81a
--- /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 000000000..ad9894975
--- /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 000000000..b18703dcf
--- /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 000000000..c9303270e
--- /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 000000000..5ccc7dbc3
--- /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 000000000..1ee8224cc
--- /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 000000000..bb013d9dc
--- /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 000000000..162185ba6
--- /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 000000000..f47d1ee85
--- /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 000000000..8062d1937
--- /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 000000000..297ee33de
--- /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 000000000..8a767902b
--- /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 000000000..2ce711426
--- /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 000000000..250dccbb1
--- /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 000000000..9620b44f2
--- /dev/null
+++ b/src/boost/libs/poly_collection/test/test_construction.cpp
@@ -0,0 +1,375 @@
+/* Copyright 2016-2020 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(AlwaysEqual)BOOST_TEST(d2==d3);
+
+ 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 000000000..4b7109e26
--- /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 000000000..a3bd4ec78
--- /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 000000000..cf4acc759
--- /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 000000000..56cfba240
--- /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 000000000..9f29930e1
--- /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 000000000..45d0644a8
--- /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 000000000..685393295
--- /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 000000000..997ee1bd0
--- /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 000000000..22099bbee
--- /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 000000000..920a7a416
--- /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 000000000..999158fd0
--- /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 000000000..98ccfaa49
--- /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 000000000..8a2cae90e
--- /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 000000000..e8bd1204e
--- /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 000000000..05e439d6b
--- /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 000000000..0c927fd1b
--- /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 000000000..0b6ab5fc4
--- /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 000000000..e09f9dcaf
--- /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