summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/container/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/container/test')
-rw-r--r--src/boost/libs/container/test/Jamfile.v240
-rw-r--r--src/boost/libs/container/test/alloc_basic_test.cpp119
-rw-r--r--src/boost/libs/container/test/alloc_full_test.cpp849
-rw-r--r--src/boost/libs/container/test/allocator_argument_tester.hpp233
-rw-r--r--src/boost/libs/container/test/allocator_traits_test.cpp447
-rw-r--r--src/boost/libs/container/test/check_equal_containers.hpp159
-rw-r--r--src/boost/libs/container/test/comparison_test.hpp58
-rw-r--r--src/boost/libs/container/test/container_common_tests.hpp86
-rw-r--r--src/boost/libs/container/test/default_init_test.hpp155
-rw-r--r--src/boost/libs/container/test/deque_options_test.cpp43
-rw-r--r--src/boost/libs/container/test/deque_test.cpp446
-rw-r--r--src/boost/libs/container/test/derived_from_memory_resource.hpp87
-rw-r--r--src/boost/libs/container/test/dummy_test_allocator.hpp232
-rw-r--r--src/boost/libs/container/test/emplace_test.hpp686
-rw-r--r--src/boost/libs/container/test/expand_bwd_test_allocator.hpp200
-rw-r--r--src/boost/libs/container/test/expand_bwd_test_template.hpp218
-rw-r--r--src/boost/libs/container/test/explicit_inst_deque_test.cpp46
-rw-r--r--src/boost/libs/container/test/explicit_inst_flat_map_test.cpp94
-rw-r--r--src/boost/libs/container/test/explicit_inst_flat_set_test.cpp88
-rw-r--r--src/boost/libs/container/test/explicit_inst_list_test.cpp25
-rw-r--r--src/boost/libs/container/test/explicit_inst_map_test.cpp56
-rw-r--r--src/boost/libs/container/test/explicit_inst_set_test.cpp54
-rw-r--r--src/boost/libs/container/test/explicit_inst_slist_test.cpp44
-rw-r--r--src/boost/libs/container/test/explicit_inst_small_vector_test.cpp56
-rw-r--r--src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp45
-rw-r--r--src/boost/libs/container/test/explicit_inst_static_vector_test.cpp33
-rw-r--r--src/boost/libs/container/test/explicit_inst_string_test.cpp44
-rw-r--r--src/boost/libs/container/test/explicit_inst_vector_test.cpp47
-rw-r--r--src/boost/libs/container/test/flat_map_adaptor_test.cpp104
-rw-r--r--src/boost/libs/container/test/flat_map_test.cpp838
-rw-r--r--src/boost/libs/container/test/flat_set_adaptor_test.cpp101
-rw-r--r--src/boost/libs/container/test/flat_set_test.cpp933
-rw-r--r--src/boost/libs/container/test/flat_tree_test.cpp156
-rw-r--r--src/boost/libs/container/test/global_resource_test.cpp127
-rw-r--r--src/boost/libs/container/test/hash_table_test.cppx0
-rw-r--r--src/boost/libs/container/test/input_from_forward_iterator.hpp80
-rw-r--r--src/boost/libs/container/test/insert_test.hpp75
-rw-r--r--src/boost/libs/container/test/insert_vs_emplace_test.cpp498
-rw-r--r--src/boost/libs/container/test/list_test.cpp286
-rw-r--r--src/boost/libs/container/test/list_test.hpp469
-rw-r--r--src/boost/libs/container/test/map_test.cpp693
-rw-r--r--src/boost/libs/container/test/map_test.hpp1264
-rw-r--r--src/boost/libs/container/test/memory_resource_logger.hpp86
-rw-r--r--src/boost/libs/container/test/memory_resource_test.cpp135
-rw-r--r--src/boost/libs/container/test/monotonic_buffer_resource_test.cpp483
-rw-r--r--src/boost/libs/container/test/movable_int.hpp437
-rw-r--r--src/boost/libs/container/test/node_handle_test.cpp633
-rw-r--r--src/boost/libs/container/test/null_iterators_test.cpp96
-rw-r--r--src/boost/libs/container/test/pair_test.cpp156
-rw-r--r--src/boost/libs/container/test/pmr_deque_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_flat_map_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_flat_set_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_list_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_map_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_set_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_slist_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_small_vector_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_stable_vector_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_static_vector_test.cpp26
-rw-r--r--src/boost/libs/container/test/pmr_string_test.cpp31
-rw-r--r--src/boost/libs/container/test/pmr_vector_test.cpp26
-rw-r--r--src/boost/libs/container/test/polymorphic_allocator_test.cpp198
-rw-r--r--src/boost/libs/container/test/pool_resource_test.hpp493
-rw-r--r--src/boost/libs/container/test/print_container.hpp46
-rw-r--r--src/boost/libs/container/test/propagate_allocator_test.hpp368
-rw-r--r--src/boost/libs/container/test/propagation_test_allocator.hpp268
-rw-r--r--src/boost/libs/container/test/resource_adaptor_test.cpp234
-rw-r--r--src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp1377
-rw-r--r--src/boost/libs/container/test/scoped_allocator_usage_test.cpp428
-rw-r--r--src/boost/libs/container/test/set_test.cpp655
-rw-r--r--src/boost/libs/container/test/set_test.hpp942
-rw-r--r--src/boost/libs/container/test/slist_test.cpp290
-rw-r--r--src/boost/libs/container/test/small_vector_options_test.cpp110
-rw-r--r--src/boost/libs/container/test/small_vector_test.cpp236
-rw-r--r--src/boost/libs/container/test/stable_vector_test.cpp227
-rw-r--r--src/boost/libs/container/test/static_vector_options_test.cpp124
-rw-r--r--src/boost/libs/container/test/static_vector_test.cpp827
-rw-r--r--src/boost/libs/container/test/static_vector_test.hpp103
-rw-r--r--src/boost/libs/container/test/string_test.cpp596
-rw-r--r--src/boost/libs/container/test/string_view_compat_test.cpp275
-rw-r--r--src/boost/libs/container/test/synchronized_pool_resource_test.cpp19
-rw-r--r--src/boost/libs/container/test/throw_exception_test.cpp62
-rw-r--r--src/boost/libs/container/test/tree_test.cpp119
-rw-r--r--src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp19
-rw-r--r--src/boost/libs/container/test/uses_allocator_test.cpp84
-rw-r--r--src/boost/libs/container/test/vector_options_test.cpp121
-rw-r--r--src/boost/libs/container/test/vector_test.cpp364
-rw-r--r--src/boost/libs/container/test/vector_test.hpp563
88 files changed, 21805 insertions, 0 deletions
diff --git a/src/boost/libs/container/test/Jamfile.v2 b/src/boost/libs/container/test/Jamfile.v2
new file mode 100644
index 000000000..2b4995bee
--- /dev/null
+++ b/src/boost/libs/container/test/Jamfile.v2
@@ -0,0 +1,40 @@
+# Boost Container Library Test Jamfile
+
+# (C) Copyright Ion Gaztanaga 2009-2013.
+# Use, modification and distribution are subject to 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)
+
+# Adapted from John Maddock's TR1 Jamfile.v2
+# Copyright John Maddock 2005.
+# Use, modification and distribution are subject to 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)
+
+project
+ : requirements
+ <link>shared:<define>BOOST_CONTAINER_DYN_LINK=1
+ <toolset>gcc-cygwin:<link>static
+ ;
+
+# this rule enumerates through all the sources and invokes
+# the run rule for each source, the result is a list of all
+# the run rules, which we can pass on to the test_suite rule:
+
+rule test_all
+{
+ local all_rules = ;
+
+ for local fileb in [ glob *.cpp ]
+ {
+ all_rules += [ run $(fileb) /boost/container//boost_container
+ : # additional args
+ : # test-files
+ : # requirements
+ ] ;
+ }
+
+ return $(all_rules) ;
+}
+
+test-suite container_test : [ test_all r ] ;
diff --git a/src/boost/libs/container/test/alloc_basic_test.cpp b/src/boost/libs/container/test/alloc_basic_test.cpp
new file mode 100644
index 000000000..4bfdcf48b
--- /dev/null
+++ b/src/boost/libs/container/test/alloc_basic_test.cpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/dlmalloc.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/list.hpp>
+
+using namespace boost::container;
+
+bool basic_test()
+{
+ size_t received = 0;
+ if(!dlmalloc_all_deallocated())
+ return false;
+ void *ptr = dlmalloc_alloc(50, 98, &received);
+ if(dlmalloc_size(ptr) != received)
+ return false;
+ if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+ return false;
+
+ if(dlmalloc_all_deallocated())
+ return false;
+
+ dlmalloc_grow(ptr, received + 20, received + 30, &received);
+
+ if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+ return false;
+
+ if(dlmalloc_size(ptr) != received)
+ return false;
+
+ if(!dlmalloc_shrink(ptr, 100, 140, &received, 1))
+ return false;
+
+ if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+ return false;
+
+ if(!dlmalloc_shrink(ptr, 0, 140, &received, 1))
+ return false;
+
+ if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+ return false;
+
+ if(dlmalloc_shrink(ptr, 0, received/2, &received, 1))
+ return false;
+
+ if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+ return false;
+
+ if(dlmalloc_size(ptr) != received)
+ return false;
+
+ dlmalloc_free(ptr);
+
+ dlmalloc_malloc_check();
+ if(!dlmalloc_all_deallocated())
+ return false;
+ return true;
+}
+
+bool vector_test()
+{
+ typedef boost::container::vector<int, allocator<int> > Vector;
+ if(!dlmalloc_all_deallocated())
+ return false;
+ {
+ const int NumElem = 1000;
+ Vector v;
+ v.resize(NumElem);
+ int *orig_buf = &v[0];
+ int *new_buf = &v[0];
+ while(orig_buf == new_buf){
+ Vector::size_type cl = v.capacity() - v.size();
+ while(cl--){
+ v.push_back(0);
+ }
+ v.push_back(0);
+ new_buf = &v[0];
+ }
+ }
+ if(!dlmalloc_all_deallocated())
+ return false;
+ return true;
+}
+
+bool list_test()
+{
+ typedef boost::container::list<int, allocator<int> > List;
+ if(!dlmalloc_all_deallocated())
+ return false;
+ {
+ const int NumElem = 1000;
+ List l;
+ int values[NumElem];
+ l.insert(l.end(), &values[0], &values[NumElem]);
+ }
+ if(!dlmalloc_all_deallocated())
+ return false;
+ return true;
+}
+
+int main()
+{
+ if(!basic_test())
+ return 1;
+ if(!vector_test())
+ return 1;
+ if(!list_test())
+ return 1;
+ return 0;
+}
diff --git a/src/boost/libs/container/test/alloc_full_test.cpp b/src/boost/libs/container/test/alloc_full_test.cpp
new file mode 100644
index 000000000..54e1160c9
--- /dev/null
+++ b/src/boost/libs/container/test/alloc_full_test.cpp
@@ -0,0 +1,849 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifdef _MSC_VER
+#pragma warning (disable:4702)
+#endif
+
+#include <vector>
+#include <iostream>
+#include <cstring>
+#include <algorithm> //std::remove
+#include <boost/container/detail/dlmalloc.hpp>
+
+namespace boost { namespace container { namespace test {
+
+static const int NumIt = 200;
+
+enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType };
+
+//This test allocates until there is no more memory
+//and after that deallocates all in the inverse order
+
+bool test_allocation()
+{
+ if(!dlmalloc_all_deallocated())
+ return false;
+ dlmalloc_malloc_check();
+ for( deallocation_type t = DirectDeallocation
+ ; t != EndDeallocationType
+ ; t = (deallocation_type)((int)t + 1)){
+ std::vector<void*> buffers;
+ //std::size_t free_memory = a.get_free_memory();
+
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i);
+ if(!ptr)
+ break;
+ buffers.push_back(ptr);
+ }
+
+ switch(t){
+ case DirectDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case InverseDeallocation:
+ {
+ for(int j = (int)buffers.size()
+ ;j--
+ ;){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case MixedDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if(!dlmalloc_all_deallocated())
+ return false;
+ //bool ok = free_memory == a.get_free_memory() &&
+ //a.all_memory_deallocated() && a.check_sanity();
+ //if(!ok) return ok;
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to shrink all the buffers to the
+//half of the original size
+
+bool test_allocation_shrink()
+{
+ dlmalloc_malloc_check();
+ std::vector<void*> buffers;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i*2);
+ if(!ptr)
+ break;
+ buffers.push_back(ptr);
+ }
+
+ //Now shrink to half
+ for(int i = 0, max = (int)buffers.size()
+ ;i < max
+ ; ++i){
+ std::size_t try_received_size = 0;
+ void* try_result = dlmalloc_allocation_command
+ ( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 1, i*2
+ , i, &try_received_size, (char*)buffers[i]).first;
+
+ std::size_t received_size = 0;
+ void* result = dlmalloc_allocation_command
+ ( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, i*2
+ , i, &received_size, (char*)buffers[i]).first;
+
+ if(result != try_result)
+ return false;
+
+ if(received_size != try_received_size)
+ return false;
+
+ if(result){
+ if(received_size > std::size_t(i*2)){
+ return false;
+ }
+ if(received_size < std::size_t(i)){
+ return false;
+ }
+ }
+ }
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to expand all the buffers to
+//avoid the wasted internal fragmentation
+
+bool test_allocation_expand()
+{
+ dlmalloc_malloc_check();
+ std::vector<void*> buffers;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i);
+ if(!ptr)
+ break;
+ buffers.push_back(ptr);
+ }
+
+ //Now try to expand to the double of the size
+ for(int i = 0, max = (int)buffers.size()
+ ;i < max
+ ;++i){
+ std::size_t received_size = 0;
+ std::size_t min_size = i+1;
+ std::size_t preferred_size = i*2;
+ preferred_size = min_size > preferred_size ? min_size : preferred_size;
+ while(dlmalloc_allocation_command
+ ( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
+ , preferred_size, &received_size, (char*)buffers[i]).first){
+ //Check received size is bigger than minimum
+ if(received_size < min_size){
+ return false;
+ }
+ //Now, try to expand further
+ min_size = received_size+1;
+ preferred_size = min_size*2;
+ }
+ }
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to expand all the buffers to
+//avoid the wasted internal fragmentation
+bool test_allocation_shrink_and_expand()
+{
+ std::vector<void*> buffers;
+ std::vector<std::size_t> received_sizes;
+ std::vector<bool> size_reduced;
+
+ //Allocate buffers wand store received sizes
+ for(int i = 0; i != NumIt; ++i){
+ std::size_t received_size = 0;
+ void *ptr = dlmalloc_allocation_command
+ (BOOST_CONTAINER_ALLOCATE_NEW, 1, i, i*2, &received_size, 0).first;
+ if(!ptr){
+ ptr = dlmalloc_allocation_command
+ ( BOOST_CONTAINER_ALLOCATE_NEW, 1, 1, i*2, &received_size, 0).first;
+ if(!ptr)
+ break;
+ }
+ buffers.push_back(ptr);
+ received_sizes.push_back(received_size);
+ }
+
+ //Now shrink to half
+ for(int i = 0, max = (int)buffers.size()
+ ; i < max
+ ; ++i){
+ std::size_t received_size = 0;
+ bool size_reduced_flag;
+ if(true == (size_reduced_flag = !!
+ dlmalloc_allocation_command
+ ( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, received_sizes[i]
+ , i, &received_size, (char*)buffers[i]).first)){
+ if(received_size > std::size_t(received_sizes[i])){
+ return false;
+ }
+ if(received_size < std::size_t(i)){
+ return false;
+ }
+ }
+ size_reduced.push_back(size_reduced_flag);
+ }
+
+ //Now try to expand to the original size
+ for(int i = 0, max = (int)buffers.size()
+ ;i < max
+ ;++i){
+ if(!size_reduced[i]) continue;
+ std::size_t received_size = 0;
+ std::size_t request_size = received_sizes[i];
+ if(dlmalloc_allocation_command
+ ( BOOST_CONTAINER_EXPAND_FWD, 1, request_size
+ , request_size, &received_size, (char*)buffers[i]).first){
+ if(received_size != request_size){
+ return false;
+ }
+ }
+ else{
+ return false;
+ }
+ }
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that deallocates the odd buffers to
+//make room for expansions. The expansion will probably
+//success since the deallocation left room for that.
+
+bool test_allocation_deallocation_expand()
+{
+ dlmalloc_malloc_check();
+ std::vector<void*> buffers;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i);
+ if(!ptr)
+ break;
+ buffers.push_back(ptr);
+ }
+
+ //Now deallocate the half of the blocks
+ //so expand maybe can merge new free blocks
+ for(int i = 0, max = (int)buffers.size()
+ ;i < max
+ ;++i){
+ if(i%2){
+ dlmalloc_free(buffers[i]);
+ buffers[i] = 0;
+ }
+ }
+
+ //Now try to expand to the double of the size
+ for(int i = 0, max = (int)buffers.size()
+ ;i < max
+ ;++i){
+ //
+ if(buffers[i]){
+ std::size_t received_size = 0;
+ std::size_t min_size = i+1;
+ std::size_t preferred_size = i*2;
+ preferred_size = min_size > preferred_size ? min_size : preferred_size;
+
+ while(dlmalloc_allocation_command
+ ( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
+ , preferred_size, &received_size, (char*)buffers[i]).first){
+ //Check received size is bigger than minimum
+ if(received_size < min_size){
+ return false;
+ }
+ //Now, try to expand further
+ min_size = received_size+1;
+ preferred_size = min_size*2;
+ }
+ }
+ }
+
+ //Now erase null values from the vector
+ buffers.erase(std::remove(buffers.begin(), buffers.end(), (void*)0)
+ ,buffers.end());
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that deallocates all except the last.
+//If the allocation algorithm is a bottom-up algorithm
+//the last buffer will be in the end of the segment.
+//Then the test will start expanding backwards, until
+//the buffer fills all the memory
+
+bool test_allocation_with_reuse()
+{
+ dlmalloc_malloc_check();
+ //We will repeat this test for different sized elements
+ for(int sizeof_object = 1; sizeof_object < 20; ++sizeof_object){
+ std::vector<void*> buffers;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i*sizeof_object);
+ if(!ptr)
+ break;
+ buffers.push_back(ptr);
+ }
+
+ //Now deallocate all except the latest
+ //Now try to expand to the double of the size
+ for(int i = 0, max = (int)buffers.size() - 1
+ ;i < max
+ ;++i){
+ dlmalloc_free(buffers[i]);
+ }
+
+ //Save the unique buffer and clear vector
+ void *ptr = buffers.back();
+ buffers.clear();
+
+ //Now allocate with reuse
+ std::size_t received_size = 0;
+ for(int i = 0; i != NumIt; ++i){
+ std::size_t min_size = (received_size/sizeof_object + 1)*sizeof_object;
+ std::size_t prf_size = (received_size/sizeof_object + (i+1)*2)*sizeof_object;
+ dlmalloc_command_ret_t ret = dlmalloc_allocation_command
+ ( BOOST_CONTAINER_EXPAND_BWD, sizeof_object, min_size
+ , prf_size, &received_size, (char*)ptr);
+ //If we have memory, this must be a buffer reuse
+ if(!ret.first)
+ break;
+ //If we have memory, this must be a buffer reuse
+ if(!ret.second)
+ return false;
+ if(received_size < min_size)
+ return false;
+ ptr = ret.first;
+ }
+ //There should be only a single block so deallocate it
+ dlmalloc_free(ptr);
+ dlmalloc_malloc_check();
+ if(!dlmalloc_all_deallocated())
+ return false;
+ }
+ return true;
+}
+
+
+//This test allocates memory with different alignments
+//and checks returned memory is aligned.
+
+bool test_aligned_allocation()
+{
+ dlmalloc_malloc_check();
+ //Allocate aligned buffers in a loop
+ //and then deallocate it
+ for(unsigned int i = 1; i != (1 << (sizeof(int)/2)); i <<= 1){
+ for(unsigned int j = 1; j != 512; j <<= 1){
+ void *ptr = dlmalloc_memalign(i-1, j);
+ if(!ptr){
+ return false;
+ }
+
+ if(((std::size_t)ptr & (j - 1)) != 0)
+ return false;
+ dlmalloc_free(ptr);
+ //if(!a.all_memory_deallocated() || !a.check_sanity()){
+ // return false;
+ //}
+ }
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates memory with different alignments
+//and checks returned memory is aligned.
+
+bool test_continuous_aligned_allocation()
+{
+ dlmalloc_malloc_check();
+ std::vector<void*> buffers;
+ //Allocate aligned buffers in a loop
+ //and then deallocate it
+ bool continue_loop = true;
+ unsigned int MaxAlign = 4096;
+ unsigned int MaxSize = 4096;
+ for(unsigned i = 1; i < MaxSize; i <<= 1){
+ for(unsigned int j = 1; j < MaxAlign; j <<= 1){
+ for(int k = 0; k != NumIt; ++k){
+ void *ptr = dlmalloc_memalign(i-1, j);
+ buffers.push_back(ptr);
+ if(!ptr){
+ continue_loop = false;
+ break;
+ }
+
+ if(((std::size_t)ptr & (j - 1)) != 0)
+ return false;
+ }
+ //Deallocate all
+ for(int k = (int)buffers.size(); k--;){
+ dlmalloc_free(buffers[k]);
+ }
+ buffers.clear();
+ //if(!a.all_memory_deallocated() && a.check_sanity())
+ // return false;
+ if(!continue_loop)
+ break;
+ }
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates multiple values until there is no more memory
+//and after that deallocates all in the inverse order
+bool test_many_equal_allocation()
+{
+ dlmalloc_malloc_check();
+ for( deallocation_type t = DirectDeallocation
+ ; t != EndDeallocationType
+ ; t = (deallocation_type)((int)t + 1)){
+ //std::size_t free_memory = a.get_free_memory();
+
+ std::vector<void*> buffers2;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i);
+ if(!ptr)
+ break;
+ //if(!a.check_sanity())
+ //return false;
+ buffers2.push_back(ptr);
+ }
+
+ //Now deallocate the half of the blocks
+ //so expand maybe can merge new free blocks
+ for(int i = 0, max = (int)buffers2.size()
+ ;i < max
+ ;++i){
+ if(i%2){
+ dlmalloc_free(buffers2[i]);
+ buffers2[i] = 0;
+ }
+ }
+
+ //if(!a.check_sanity())
+ //return false;
+
+ std::vector<void*> buffers;
+ for(int i = 0; i != NumIt/10; ++i){
+ dlmalloc_memchain chain;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+ dlmalloc_multialloc_nodes((i+1)*2, i+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+ dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+ if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+ break;
+
+ std::size_t n = 0;
+ for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
+ buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
+ BOOST_CONTAINER_MEMIT_NEXT(it);
+ }
+ if(n != std::size_t((i+1)*2))
+ return false;
+ }
+
+ //if(!a.check_sanity())
+ //return false;
+
+ switch(t){
+ case DirectDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case InverseDeallocation:
+ {
+ for(int j = (int)buffers.size()
+ ;j--
+ ;){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case MixedDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ //Deallocate the rest of the blocks
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers2.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers2.size())/4;
+ dlmalloc_free(buffers2[pos]);
+ buffers2.erase(buffers2.begin()+pos);
+ }
+
+ //bool ok = free_memory == a.get_free_memory() &&
+ //a.all_memory_deallocated() && a.check_sanity();
+ //if(!ok) return ok;
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();
+}
+
+//This test allocates multiple values until there is no more memory
+//and after that deallocates all in the inverse order
+
+bool test_many_different_allocation()
+{
+ dlmalloc_malloc_check();
+ const std::size_t ArraySize = 11;
+ std::size_t requested_sizes[ArraySize];
+ for(std::size_t i = 0; i < ArraySize; ++i){
+ requested_sizes[i] = 4*i;
+ }
+
+ for( deallocation_type t = DirectDeallocation
+ ; t != EndDeallocationType
+ ; t = (deallocation_type)((int)t + 1)){
+ //std::size_t free_memory = a.get_free_memory();
+
+ std::vector<void*> buffers2;
+
+ //Allocate buffers with extra memory
+ for(int i = 0; i != NumIt; ++i){
+ void *ptr = dlmalloc_malloc(i);
+ if(!ptr)
+ break;
+ buffers2.push_back(ptr);
+ }
+
+ //Now deallocate the half of the blocks
+ //so expand maybe can merge new free blocks
+ for(int i = 0, max = (int)buffers2.size()
+ ;i < max
+ ;++i){
+ if(i%2){
+ dlmalloc_free(buffers2[i]);
+ buffers2[i] = 0;
+ }
+ }
+
+ std::vector<void*> buffers;
+ for(int i = 0; i != NumIt; ++i){
+ dlmalloc_memchain chain;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+ dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+ dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+ if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+ break;
+ std::size_t n = 0;
+ for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
+ buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
+ BOOST_CONTAINER_MEMIT_NEXT(it);
+ }
+ if(n != ArraySize)
+ return false;
+ }
+
+ switch(t){
+ case DirectDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case InverseDeallocation:
+ {
+ for(int j = (int)buffers.size()
+ ;j--
+ ;){
+ dlmalloc_free(buffers[j]);
+ }
+ }
+ break;
+ case MixedDeallocation:
+ {
+ for(int j = 0, max = (int)buffers.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers.size())/4;
+ dlmalloc_free(buffers[pos]);
+ buffers.erase(buffers.begin()+pos);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ //Deallocate the rest of the blocks
+
+ //Deallocate it in non sequential order
+ for(int j = 0, max = (int)buffers2.size()
+ ;j < max
+ ;++j){
+ int pos = (j%4)*((int)buffers2.size())/4;
+ dlmalloc_free(buffers2[pos]);
+ buffers2.erase(buffers2.begin()+pos);
+ }
+
+ //bool ok = free_memory == a.get_free_memory() &&
+ //a.all_memory_deallocated() && a.check_sanity();
+ //if(!ok) return ok;
+ }
+ dlmalloc_malloc_check();
+ return 0 != dlmalloc_all_deallocated();
+}
+
+bool test_many_deallocation()
+{
+ const std::size_t ArraySize = 11;
+ std::vector<dlmalloc_memchain> buffers;
+ std::size_t requested_sizes[ArraySize];
+ for(std::size_t i = 0; i < ArraySize; ++i){
+ requested_sizes[i] = 4*i;
+ }
+
+ for(int i = 0; i != NumIt; ++i){
+ dlmalloc_memchain chain;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+ dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+ dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+ if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+ return false;
+ buffers.push_back(chain);
+ }
+ for(int i = 0; i != NumIt; ++i){
+ dlmalloc_multidealloc(&buffers[i]);
+ }
+ buffers.clear();
+
+ dlmalloc_malloc_check();
+ if(!dlmalloc_all_deallocated())
+ return false;
+
+ for(int i = 0; i != NumIt; ++i){
+ dlmalloc_memchain chain;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+ dlmalloc_multialloc_nodes(ArraySize, i*4+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+ dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+ if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+ return false;
+ buffers.push_back(chain);
+ }
+ for(int i = 0; i != NumIt; ++i){
+ dlmalloc_multidealloc(&buffers[i]);
+ }
+ buffers.clear();
+
+ dlmalloc_malloc_check();
+ if(!dlmalloc_all_deallocated())
+ return false;
+
+ return true;
+}
+
+//This function calls all tests
+
+bool test_all_allocation()
+{
+ std::cout << "Starting test_allocation"
+ << std::endl;
+
+ if(!test_allocation()){
+ std::cout << "test_allocation_direct_deallocation failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_many_equal_allocation"
+ << std::endl;
+
+ if(!test_many_equal_allocation()){
+ std::cout << "test_many_equal_allocation failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_many_different_allocation"
+ << std::endl;
+
+ if(!test_many_different_allocation()){
+ std::cout << "test_many_different_allocation failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_allocation_shrink"
+ << std::endl;
+
+ if(!test_allocation_shrink()){
+ std::cout << "test_allocation_shrink failed"
+ << std::endl;
+ return false;
+ }
+
+ if(!test_allocation_shrink_and_expand()){
+ std::cout << "test_allocation_shrink_and_expand failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_allocation_expand"
+ << std::endl;
+
+ if(!test_allocation_expand()){
+ std::cout << "test_allocation_expand failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_allocation_deallocation_expand"
+ << std::endl;
+
+ if(!test_allocation_deallocation_expand()){
+ std::cout << "test_allocation_deallocation_expand failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_allocation_with_reuse"
+ << std::endl;
+
+ if(!test_allocation_with_reuse()){
+ std::cout << "test_allocation_with_reuse failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_aligned_allocation"
+ << std::endl;
+
+ if(!test_aligned_allocation()){
+ std::cout << "test_aligned_allocation failed"
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_continuous_aligned_allocation"
+ << std::endl;
+
+ if(!test_continuous_aligned_allocation()){
+ std::cout << "test_continuous_aligned_allocation failed"
+ << std::endl;
+ return false;
+ }
+
+ if(!test_many_deallocation()){
+ std::cout << "test_many_deallocation failed"
+ << std::endl;
+ return false;
+ }
+
+ return 0 != dlmalloc_all_deallocated();
+}
+
+}}} //namespace boost { namespace container { namespace test {
+
+
+int main()
+{
+ if(!boost::container::test::test_all_allocation())
+ return 1;
+ return 0;
+}
diff --git a/src/boost/libs/container/test/allocator_argument_tester.hpp b/src/boost/libs/container/test/allocator_argument_tester.hpp
new file mode 100644
index 000000000..73993285e
--- /dev/null
+++ b/src/boost/libs/container/test/allocator_argument_tester.hpp
@@ -0,0 +1,233 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+
+#include <boost/container/uses_allocator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/core.hpp>
+
+template<class T, unsigned int Id, bool HasTrueTypes = false>
+class propagation_test_allocator
+{
+ BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+ public:
+
+ template<class U>
+ struct rebind
+ {
+ typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
+ };
+
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_move_assignment;
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_swap;
+ typedef boost::container::dtl::bool_<HasTrueTypes> is_always_equal;
+ typedef T value_type;
+
+ propagation_test_allocator()
+ : m_move_contructed(false), m_move_assigned(false)
+ {}
+
+ propagation_test_allocator(const propagation_test_allocator&)
+ : m_move_contructed(false), m_move_assigned(false)
+ {}
+
+ propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
+ : m_move_contructed(true), m_move_assigned(false)
+ {}
+
+ template<class U>
+ propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
+ : m_move_contructed(true), m_move_assigned(false)
+ {}
+
+ template<class U>
+ propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
+ {}
+
+ propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
+ {
+ return *this;
+ }
+
+ propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
+ {
+ m_move_assigned = true;
+ return *this;
+ }
+
+ std::size_t max_size() const
+ { return std::size_t(-1); }
+
+ T* allocate(std::size_t n)
+ { return (T*)::new char[n*sizeof(T)]; }
+
+ void deallocate(T*p, std::size_t)
+ { delete []static_cast<char*>(static_cast<void*>(p)); }
+
+ bool m_move_contructed;
+ bool m_move_assigned;
+};
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+ , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{ return true; }
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+ , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{ return false; }
+
+//This enum lists the construction options
+//for an allocator-aware type
+enum ConstructionTypeEnum
+{
+ ConstructiblePrefix,
+ ConstructibleSuffix,
+ NotUsesAllocator
+};
+
+//This base class provices types for
+//the derived class to implement each construction
+//type. If a construction type does not apply
+//the typedef is set to an internal nat
+//so that the class is not constructible from
+//the user arguments.
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct uses_allocator_base;
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
+{
+ typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+ typedef allocator_type allocator_constructor_type;
+ struct nat{};
+ typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
+{
+ typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+ typedef allocator_type allocator_constructor_type;
+ typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
+{
+ struct nat{};
+ typedef nat allocator_constructor_type;
+ typedef nat allocator_arg_type;
+};
+
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct allocator_argument_tester
+ : uses_allocator_base<ConstructionType, AllocatorTag>
+{
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
+
+ public:
+
+ typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
+
+ //0 user argument constructors
+ allocator_argument_tester()
+ : construction_type(NotUsesAllocator), value(0)
+ {}
+
+ explicit allocator_argument_tester
+ (typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(0)
+ {}
+
+ explicit allocator_argument_tester
+ (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
+ : construction_type(ConstructiblePrefix), value(0)
+ {}
+
+ //1 user argument constructors
+ explicit allocator_argument_tester(int i)
+ : construction_type(NotUsesAllocator), value(i)
+ {}
+
+ allocator_argument_tester
+ (int i, typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(i)
+ {}
+
+ allocator_argument_tester
+ ( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , int i)
+ : construction_type(ConstructiblePrefix), value(i)
+ {}
+
+ //Copy constructors
+ allocator_argument_tester(const allocator_argument_tester &other)
+ : construction_type(NotUsesAllocator), value(other.value)
+ {}
+
+ allocator_argument_tester( const allocator_argument_tester &other
+ , typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(other.value)
+ {}
+
+ allocator_argument_tester( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , const allocator_argument_tester &other)
+ : construction_type(ConstructiblePrefix), value(other.value)
+ {}
+
+ //Move constructors
+ allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
+ : construction_type(NotUsesAllocator), value(other.value)
+ { other.value = 0; other.construction_type = NotUsesAllocator; }
+
+ allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
+ , typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(other.value)
+ { other.value = 0; other.construction_type = ConstructibleSuffix; }
+
+ allocator_argument_tester( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , BOOST_RV_REF(allocator_argument_tester) other)
+ : construction_type(ConstructiblePrefix), value(other.value)
+ { other.value = 0; other.construction_type = ConstructiblePrefix; }
+
+ ConstructionTypeEnum construction_type;
+ int value;
+};
+
+namespace boost {
+namespace container {
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+ < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+ < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
diff --git a/src/boost/libs/container/test/allocator_traits_test.cpp b/src/boost/libs/container/test/allocator_traits_test.cpp
new file mode 100644
index 000000000..401442414
--- /dev/null
+++ b/src/boost/libs/container/test/allocator_traits_test.cpp
@@ -0,0 +1,447 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <cstddef>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/function_detector.hpp>
+#include <boost/move/utility_core.hpp>
+#include <memory>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/core/lightweight_test.hpp>
+
+template<class T>
+class SimpleAllocator
+{
+ public:
+ bool allocate_called_;
+ bool deallocate_called_;
+
+ typedef boost::container::dtl::
+ true_type is_always_equal;
+
+ typedef T value_type;
+
+ template <class U>
+ SimpleAllocator(SimpleAllocator<U>)
+ : allocate_called_(false)
+ , deallocate_called_(false)
+ {}
+
+ SimpleAllocator()
+ : allocate_called_(false)
+ , deallocate_called_(false)
+ {}
+
+ T* allocate(std::size_t)
+ { allocate_called_ = true; return 0; }
+
+ void deallocate(T*, std::size_t)
+ { deallocate_called_ = true; }
+
+ bool allocate_called() const
+ { return allocate_called_; }
+
+ bool deallocate_called() const
+ { return deallocate_called_; }
+
+ friend bool operator==(const SimpleAllocator &, const SimpleAllocator &)
+ { return true; }
+
+ friend bool operator!=(const SimpleAllocator &, const SimpleAllocator &)
+ { return false; }
+};
+
+template<class T>
+class SimpleSmartPtr
+{
+ void unspecified_bool_type_func() const {}
+ typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
+
+ public:
+
+ typedef T* pointer;
+
+ explicit SimpleSmartPtr(pointer p = 0)
+ : ptr_(p)
+ {}
+
+ SimpleSmartPtr(const SimpleSmartPtr &c)
+ { this->ptr_ = c.ptr_; }
+
+ SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
+ { this->ptr_ = c.ptr_; }
+
+ operator unspecified_bool_type() const
+ { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; }
+
+ private:
+ T *ptr_;
+};
+
+template<class T>
+class ComplexAllocator
+{
+ public:
+ bool allocate_called_;
+ bool deallocate_called_;
+ bool allocate_hint_called_;
+ bool destroy_called_;
+ mutable bool max_size_called_;
+ mutable bool select_on_container_copy_construction_called_;
+ bool construct_called_;
+ mutable bool storage_is_unpropagable_;
+
+ typedef T value_type;
+ typedef SimpleSmartPtr<T> pointer;
+ typedef SimpleSmartPtr<const T> const_pointer;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<const T>::type const_reference;
+ typedef SimpleSmartPtr<void> void_pointer;
+ typedef SimpleSmartPtr<const void> const_void_pointer;
+ typedef signed short difference_type;
+ typedef unsigned short size_type;
+ typedef boost::container::dtl::
+ true_type propagate_on_container_copy_assignment;
+ typedef boost::container::dtl::
+ true_type propagate_on_container_move_assignment;
+ typedef boost::container::dtl::
+ true_type propagate_on_container_swap;
+ typedef boost::container::dtl::
+ true_type is_partially_propagable;
+
+ ComplexAllocator()
+ : allocate_called_(false)
+ , deallocate_called_(false)
+ , allocate_hint_called_(false)
+ , destroy_called_(false)
+ , max_size_called_(false)
+ , select_on_container_copy_construction_called_(false)
+ , construct_called_(false)
+ {}
+
+ pointer allocate(size_type)
+ { allocate_called_ = true; return pointer(); }
+
+ void deallocate(pointer, size_type)
+ { deallocate_called_ = true; }
+
+ //optional
+ ComplexAllocator select_on_container_copy_construction() const
+ { select_on_container_copy_construction_called_ = true; return *this; }
+
+ pointer allocate(size_type n, const const_void_pointer &)
+ { allocate_hint_called_ = true; return allocate(n); }
+
+ template<class U>
+ void destroy(U*)
+ { destroy_called_ = true; }
+
+ size_type max_size() const
+ { max_size_called_ = true; return size_type(size_type(0)-1); }
+
+ #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL(N)\
+ \
+ template< class U BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
+ void construct(U *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
+ { construct_called_ = true; ::new(p) U ( BOOST_MOVE_FWD##N ); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL)
+ #undef BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL
+ #else
+
+ template< class U, class ...Args>
+ void construct(U *p, BOOST_FWD_REF(Args) ...args)
+ { construct_called_ = true; ::new(p) U( ::boost::forward<Args>(args)...); }
+
+ #endif
+
+ template<class U>
+ void construct(U *p, boost::container::default_init_t)
+ { construct_called_ = true; ::new(p)U; }
+
+ bool storage_is_unpropagable(pointer p) const
+ { storage_is_unpropagable_ = true; return !p; }
+
+ //getters
+ bool allocate_called() const
+ { return allocate_called_; }
+
+ bool deallocate_called() const
+ { return deallocate_called_; }
+
+ bool allocate_hint_called() const
+ { return allocate_hint_called_; }
+
+ bool destroy_called() const
+ { return destroy_called_; }
+
+ bool max_size_called() const
+ { return max_size_called_; }
+
+ bool select_on_container_copy_construction_called() const
+ { return select_on_container_copy_construction_called_; }
+
+ bool construct_called() const
+ { return construct_called_; }
+
+ bool storage_is_unpropagable_called() const
+ { return storage_is_unpropagable_; }
+};
+
+class copymovable
+{
+ BOOST_COPYABLE_AND_MOVABLE(copymovable)
+
+ public:
+
+ bool copymoveconstructed_;
+ bool moved_;
+
+ copymovable(int, int, int)
+ : copymoveconstructed_(false), moved_(false)
+ {}
+
+ copymovable()
+ : copymoveconstructed_(false), moved_(false)
+ {}
+
+ copymovable(const copymovable &)
+ : copymoveconstructed_(true), moved_(false)
+ {}
+
+ copymovable(BOOST_RV_REF(copymovable))
+ : copymoveconstructed_(true), moved_(true)
+ {}
+
+ copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; }
+ copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; }
+
+ bool copymoveconstructed() const
+ { return copymoveconstructed_; }
+
+ bool moved() const
+ { return moved_; }
+};
+
+void test_void_allocator()
+{
+ boost::container::allocator_traits<std::allocator<void> > stdtraits; (void)stdtraits;
+ boost::container::allocator_traits<SimpleAllocator<void> > simtraits; (void)simtraits;
+ boost::container::allocator_traits<ComplexAllocator<void> > comtraits; (void)comtraits;
+}
+
+int main()
+{
+ using namespace boost::container::dtl;
+ test_void_allocator();
+
+ //SimpleAllocator
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::value_type, int>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::pointer, int*>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::const_pointer, const int*>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::void_pointer, void*>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::const_void_pointer, const void*>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::difference_type, std::ptrdiff_t>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::size_type, std::size_t>::value ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < SimpleAllocator<int> >::propagate_on_container_copy_assignment::value == false ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < SimpleAllocator<int> >::propagate_on_container_swap::value == false ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < SimpleAllocator<int> >::is_always_equal::value == true ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < SimpleAllocator<int> >::is_partially_propagable::value == false ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::rebind_traits<double>::allocator_type
+ , SimpleAllocator<double> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < SimpleAllocator<int> >::rebind_alloc<double>::value_type
+ , double >::value ));
+
+ //ComplexAllocator
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::value_type, int>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::pointer, SimpleSmartPtr<int> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::const_pointer, SimpleSmartPtr<const int> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::void_pointer, SimpleSmartPtr<void> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::const_void_pointer, SimpleSmartPtr<const void> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::difference_type, signed short>::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::size_type, unsigned short>::value ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < ComplexAllocator<int> >::propagate_on_container_copy_assignment::value == true ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < ComplexAllocator<int> >::propagate_on_container_swap::value == true ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < ComplexAllocator<int> >::is_always_equal::value == false ));
+ BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+ < ComplexAllocator<int> >::is_partially_propagable::value == true ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::rebind_traits<double>::allocator_type
+ , ComplexAllocator<double> >::value ));
+ BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+ < ComplexAllocator<int> >::rebind_alloc<double>::value_type
+ , double >::value ));
+
+ typedef ComplexAllocator<int> CAlloc;
+ typedef SimpleAllocator<int> SAlloc;
+ typedef boost::container::allocator_traits<CAlloc> CAllocTraits;
+ typedef boost::container::allocator_traits<SAlloc> SAllocTraits;
+ CAlloc c_alloc;
+ SAlloc s_alloc;
+
+ //allocate
+ CAllocTraits::allocate(c_alloc, 1);
+ BOOST_TEST(c_alloc.allocate_called());
+
+ SAllocTraits::allocate(s_alloc, 1);
+ BOOST_TEST(s_alloc.allocate_called());
+
+ //deallocate
+ CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1);
+ BOOST_TEST(c_alloc.deallocate_called());
+
+ SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1);
+ BOOST_TEST(s_alloc.deallocate_called());
+
+ //allocate with hint
+ CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer());
+ BOOST_TEST(c_alloc.allocate_hint_called());
+
+ s_alloc.allocate_called_ = false;
+ SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer());
+ BOOST_TEST(s_alloc.allocate_called());
+
+ //destroy
+ float dummy;
+ CAllocTraits::destroy(c_alloc, &dummy);
+ BOOST_TEST(c_alloc.destroy_called());
+
+ SAllocTraits::destroy(s_alloc, &dummy);
+
+ //max_size
+ CAllocTraits::max_size(c_alloc);
+ BOOST_TEST(c_alloc.max_size_called());
+
+ BOOST_TEST(SAllocTraits::size_type(-1)/sizeof(SAllocTraits::value_type) == SAllocTraits::max_size(s_alloc));
+
+ //select_on_container_copy_construction
+ CAllocTraits::select_on_container_copy_construction(c_alloc);
+ BOOST_TEST(c_alloc.select_on_container_copy_construction_called());
+
+ SAllocTraits::select_on_container_copy_construction(s_alloc);
+
+ //construct
+ {
+ copymovable c;
+ c.copymoveconstructed_ = true;
+ c.copymoveconstructed_ = true;
+ CAllocTraits::construct(c_alloc, &c);
+ BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
+ }
+ {
+ int i = 5;
+ CAllocTraits::construct(c_alloc, &i, boost::container::default_init);
+ BOOST_TEST(c_alloc.construct_called() && i == 5);
+ }
+ {
+ copymovable c;
+ copymovable c2;
+ CAllocTraits::construct(c_alloc, &c, c2);
+ BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && !c.moved());
+ }
+ {
+ copymovable c;
+ copymovable c2;
+ CAllocTraits::construct(c_alloc, &c, ::boost::move(c2));
+ BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && c.moved());
+ }
+ {
+ copymovable c;
+ c.copymoveconstructed_ = true;
+ c.copymoveconstructed_ = true;
+ SAllocTraits::construct(s_alloc, &c);
+ BOOST_TEST(!c.copymoveconstructed() && !c.moved());
+ }
+ {
+ int i = 4;
+ SAllocTraits::construct(s_alloc, &i, boost::container::default_init);
+ BOOST_TEST(i == 4);
+ }
+ {
+ copymovable c;
+ copymovable c2;
+ SAllocTraits::construct(s_alloc, &c, c2);
+ BOOST_TEST(c.copymoveconstructed() && !c.moved());
+ }
+ {
+ copymovable c;
+ copymovable c2;
+ SAllocTraits::construct(s_alloc, &c, ::boost::move(c2));
+ BOOST_TEST(c.copymoveconstructed() && c.moved());
+ }
+ {
+ copymovable c;
+ CAllocTraits::construct(c_alloc, &c, 0, 1, 2);
+ BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
+ }
+ {
+ copymovable c;
+ copymovable c2;
+ SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
+ BOOST_TEST(!c.copymoveconstructed() && !c.moved());
+ }
+ //storage_is_unpropagable
+ {
+ SAlloc s_alloc2;
+ BOOST_TEST(!SAllocTraits::storage_is_unpropagable(s_alloc, SAllocTraits::pointer()));
+ }
+ {
+ {
+ CAlloc c_alloc2;
+ CAlloc::value_type v;
+ BOOST_TEST(!CAllocTraits::storage_is_unpropagable(c_alloc, CAllocTraits::pointer(&v)));
+ BOOST_TEST(c_alloc.storage_is_unpropagable_called());
+ }
+ {
+ CAlloc c_alloc2;
+ BOOST_TEST( CAllocTraits::storage_is_unpropagable(c_alloc2, CAllocTraits::pointer()));
+ BOOST_TEST(c_alloc2.storage_is_unpropagable_called());
+ }
+
+ }
+
+ return ::boost::report_errors();
+}
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/check_equal_containers.hpp b/src/boost/libs/container/test/check_equal_containers.hpp
new file mode 100644
index 000000000..758780a7f
--- /dev/null
+++ b/src/boost/libs/container/test/check_equal_containers.hpp
@@ -0,0 +1,159 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
+#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/move/utility_core.hpp>
+
+#include <cstddef>
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template< class T1, class T2>
+bool CheckEqual( const T1 &t1, const T2 &t2
+ , typename boost::container::dtl::enable_if_c
+ <!boost::container::dtl::is_pair<T1>::value &&
+ !boost::container::dtl::is_pair<T2>::value
+ >::type* = 0)
+{ return t1 == t2; }
+
+
+template<class T1, class T2, class C1, class C2>
+bool CheckEqualIt( const T1 &i1, const T2 &i2, const C1 &c1, const C2 &c2 )
+{
+ bool c1end = i1 == c1.end();
+ bool c2end = i2 == c2.end();
+ if( c1end != c2end ){
+ return false;
+ }
+ else if(c1end){
+ return true;
+ }
+ else{
+ return CheckEqual(*i1, *i2);
+ }
+}
+
+template< class Pair1, class Pair2>
+bool CheckEqual( const Pair1 &pair1, const Pair2 &pair2
+ , typename boost::container::dtl::enable_if_c
+ <boost::container::dtl::is_pair<Pair1>::value &&
+ boost::container::dtl::is_pair<Pair2>::value
+ >::type* = 0)
+{
+ return CheckEqual(pair1.first, pair2.first) && CheckEqual(pair1.second, pair2.second);
+}
+
+//Function to check if both containers are equal
+template<class ContA
+ ,class ContB>
+bool CheckEqualContainers(const ContA &cont_a, const ContB &cont_b)
+{
+ if(cont_a.size() != cont_b.size())
+ return false;
+
+ typename ContA::const_iterator itcont_a(cont_a.begin()), itcont_a_end(cont_a.end());
+ typename ContB::const_iterator itcont_b(cont_b.begin()), itcont_b_end(cont_b.end());;
+ typename ContB::size_type dist = (typename ContB::size_type)boost::container::iterator_distance(itcont_a, itcont_a_end);
+ if(dist != cont_a.size()){
+ return false;
+ }
+ typename ContA::size_type dist2 = (typename ContA::size_type)boost::container::iterator_distance(itcont_b, itcont_b_end);
+ if(dist2 != cont_b.size()){
+ return false;
+ }
+ std::size_t i = 0;
+ for(; itcont_a != itcont_a_end; ++itcont_a, ++itcont_b, ++i){
+ if(!CheckEqual(*itcont_a, *itcont_b))
+ return false;
+ }
+ return true;
+}
+
+template<class MyBoostCont
+ ,class MyStdCont>
+bool CheckEqualPairContainers(const MyBoostCont &boostcont, const MyStdCont &stdcont)
+{
+ if(boostcont.size() != stdcont.size())
+ return false;
+
+ typedef typename MyBoostCont::key_type key_type;
+ typedef typename MyBoostCont::mapped_type mapped_type;
+
+ typename MyBoostCont::const_iterator itboost(boostcont.begin()), itboostend(boostcont.end());
+ typename MyStdCont::const_iterator itstd(stdcont.begin());
+ for(; itboost != itboostend; ++itboost, ++itstd){
+ key_type k(itstd->first);
+ if(itboost->first != k)
+ return false;
+
+ mapped_type m(itstd->second);
+ if(itboost->second != m)
+ return false;
+ }
+ return true;
+}
+
+struct less_transparent
+{
+ typedef void is_transparent;
+
+ template<class T, class U>
+ bool operator()(const T &t, const U &u) const
+ {
+ return t < u;
+ }
+};
+
+struct equal_transparent
+{
+ typedef void is_transparent;
+
+ template<class T, class U>
+ bool operator()(const T &t, const U &u) const
+ {
+ return t == u;
+ }
+};
+
+struct move_op
+{
+ template<class T>
+ typename boost::move_detail::add_rvalue_reference<T>::type operator()(T &t)
+ {
+ return boost::move(t);
+ }
+};
+
+struct const_ref_op
+{
+ template<class T>
+ const T & operator()(const T &t)
+ {
+ return t;
+ }
+
+};
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
diff --git a/src/boost/libs/container/test/comparison_test.hpp b/src/boost/libs/container/test/comparison_test.hpp
new file mode 100644
index 000000000..7f3f1b3a0
--- /dev/null
+++ b/src/boost/libs/container/test/comparison_test.hpp
@@ -0,0 +1,58 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
+#define BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
+
+#include <deque>
+#include <boost/core/lightweight_test.hpp>
+
+namespace boost {
+namespace container {
+namespace test {
+
+
+template<class Cont>
+bool test_container_comparisons()
+{
+ typedef typename Cont::value_type value_type;
+
+ Cont cont;
+ cont.push_back(value_type(1));
+ cont.push_back(value_type(2));
+ cont.push_back(value_type(3));
+
+ Cont cont_equal(cont);
+
+ Cont cont_less;
+ cont_less.push_back(value_type(1));
+ cont_less.push_back(value_type(2));
+ cont_less.push_back(value_type(2));
+
+ BOOST_TEST(cont == cont_equal);
+ BOOST_TEST(!(cont != cont_equal));
+ BOOST_TEST(cont != cont_less);
+ BOOST_TEST(cont_less < cont);
+ BOOST_TEST(cont_less <= cont);
+ BOOST_TEST(!(cont_less > cont));
+ BOOST_TEST(!(cont_less >= cont));
+ BOOST_TEST(!(cont < cont_less));
+ BOOST_TEST(!(cont <= cont_less));
+ BOOST_TEST(cont > cont_less);
+ BOOST_TEST(cont >= cont_less);
+
+ return ::boost::report_errors() == 0;
+}
+
+} //namespace test {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
diff --git a/src/boost/libs/container/test/container_common_tests.hpp b/src/boost/libs/container/test/container_common_tests.hpp
new file mode 100644
index 000000000..63e15477f
--- /dev/null
+++ b/src/boost/libs/container/test/container_common_tests.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
+#define BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+
+template<class Container>
+const Container &as_const(Container &c)
+{ return c; }
+
+//nth, index_of
+template<class Container>
+bool test_nth_index_of(Container &c)
+{
+ typename Container::iterator it;
+ typename Container::const_iterator cit;
+ typename Container::size_type sz, csz;
+ //index 0
+ it = c.nth(0);
+ sz = c.index_of(it);
+ cit = (as_const)(c).nth(0);
+ csz = (as_const)(c).index_of(cit);
+
+ if(it != c.begin())
+ return false;
+ if(cit != c.cbegin())
+ return false;
+ if(sz != 0)
+ return false;
+ if(csz != 0)
+ return false;
+
+ //index size()/2
+ const typename Container::size_type sz_div_2 = c.size()/2;
+ it = c.nth(sz_div_2);
+ sz = c.index_of(it);
+ cit = (as_const)(c).nth(sz_div_2);
+ csz = (as_const)(c).index_of(cit);
+
+ if(it != (c.begin()+sz_div_2))
+ return false;
+ if(cit != (c.cbegin()+sz_div_2))
+ return false;
+ if(sz != sz_div_2)
+ return false;
+ if(csz != sz_div_2)
+ return false;
+
+ //index size()
+ it = c.nth(c.size());
+ sz = c.index_of(it);
+ cit = (as_const)(c).nth(c.size());
+ csz = (as_const)(c).index_of(cit);
+
+ if(it != c.end())
+ return false;
+ if(cit != c.cend())
+ return false;
+ if(sz != c.size())
+ return false;
+ if(csz != c.size())
+ return false;
+ return true;
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
diff --git a/src/boost/libs/container/test/default_init_test.hpp b/src/boost/libs/container/test/default_init_test.hpp
new file mode 100644
index 000000000..2e83a361f
--- /dev/null
+++ b/src/boost/libs/container/test/default_init_test.hpp
@@ -0,0 +1,155 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2013-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
+#define BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <cstddef>
+
+namespace boost{
+namespace container {
+namespace test{
+
+//
+template<int Dummy = 0>
+class default_init_allocator_base
+{
+ protected:
+ static unsigned char s_pattern;
+ static bool s_ascending;
+
+ public:
+ static void reset_pattern(unsigned char value)
+ { s_pattern = value; }
+
+ static void set_ascending(bool enable)
+ { s_ascending = enable; }
+};
+
+template<int Dummy>
+unsigned char default_init_allocator_base<Dummy>::s_pattern = 0u;
+
+template<int Dummy>
+bool default_init_allocator_base<Dummy>::s_ascending = true;
+
+template<class Integral>
+class default_init_allocator
+ : public default_init_allocator_base<0>
+{
+ typedef default_init_allocator_base<0> base_t;
+ public:
+ typedef Integral value_type;
+
+ default_init_allocator()
+ {}
+
+ template <class U>
+ default_init_allocator(default_init_allocator<U>)
+ {}
+
+ Integral* allocate(std::size_t n)
+ {
+ //Initialize memory to a pattern
+ const std::size_t max = sizeof(Integral)*n;
+ unsigned char *puc_raw = ::new unsigned char[max];
+
+ if(base_t::s_ascending){
+ for(std::size_t i = 0; i != max; ++i){
+ puc_raw[i] = static_cast<unsigned char>(s_pattern++);
+ }
+ }
+ else{
+ for(std::size_t i = 0; i != max; ++i){
+ puc_raw[i] = static_cast<unsigned char>(s_pattern--);
+ }
+ }
+ return (Integral*)puc_raw;;
+ }
+
+ void deallocate(Integral *p, std::size_t)
+ { delete[] (unsigned char*)p; }
+};
+
+template<class Integral>
+inline bool check_ascending_byte_pattern(const Integral&t)
+{
+ const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
+ const std::size_t max = sizeof(Integral);
+ for(std::size_t i = 1; i != max; ++i){
+ if( (pch[i-1] != ((unsigned char)(pch[i]-1u))) ){
+ return false;
+ }
+ }
+ return true;
+}
+
+template<class Integral>
+inline bool check_descending_byte_pattern(const Integral&t)
+{
+ const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
+ const std::size_t max = sizeof(Integral);
+ for(std::size_t i = 1; i != max; ++i){
+ if( (pch[i-1] != ((unsigned char)(pch[i]+1u))) ){
+ return false;
+ }
+ }
+ return true;
+}
+
+template<class IntDefaultInitAllocVector>
+bool default_init_test()//Test for default initialization
+{
+ const std::size_t Capacity = 100;
+
+ {
+ test::default_init_allocator<int>::reset_pattern(0);
+ test::default_init_allocator<int>::set_ascending(true);
+ IntDefaultInitAllocVector v(Capacity, default_init);
+ typename IntDefaultInitAllocVector::iterator it = v.begin();
+ //Compare with the pattern
+ for(std::size_t i = 0; i != Capacity; ++i, ++it){
+ if(!test::check_ascending_byte_pattern(*it))
+ return false;
+ }
+ }
+ {
+ test::default_init_allocator<int>::reset_pattern(0);
+ test::default_init_allocator<int>::set_ascending(true);
+ IntDefaultInitAllocVector v(Capacity, default_init, typename IntDefaultInitAllocVector::allocator_type());
+ typename IntDefaultInitAllocVector::iterator it = v.begin();
+ //Compare with the pattern
+ for(std::size_t i = 0; i != Capacity; ++i, ++it){
+ if(!test::check_ascending_byte_pattern(*it))
+ return false;
+ }
+ }
+ {
+ test::default_init_allocator<int>::reset_pattern(100);
+ test::default_init_allocator<int>::set_ascending(false);
+ IntDefaultInitAllocVector v;
+ v.resize(Capacity, default_init);
+ typename IntDefaultInitAllocVector::iterator it = v.begin();
+ //Compare with the pattern
+ for(std::size_t i = 0; i != Capacity; ++i, ++it){
+ if(!test::check_descending_byte_pattern(*it))
+ return false;
+ }
+ }
+ return true;
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
diff --git a/src/boost/libs/container/test/deque_options_test.cpp b/src/boost/libs/container/test/deque_options_test.cpp
new file mode 100644
index 000000000..9a7a43ae9
--- /dev/null
+++ b/src/boost/libs/container/test/deque_options_test.cpp
@@ -0,0 +1,43 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/deque.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+void test_block_bytes()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = deque_options_t< block_bytes<128u> >;
+ #else
+ typedef deque_options< block_bytes<128u> >::type options_t;
+ #endif
+ typedef deque<unsigned short, void, options_t> deque_t;
+ BOOST_TEST(deque_t::get_block_size() == 128u/sizeof(unsigned short));
+}
+
+void test_block_elements()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = deque_options_t< block_size<64> >;
+ #else
+ typedef deque_options< block_size<64 > >::type options_t;
+ #endif
+ typedef deque<unsigned char, void, options_t> deque_t;
+ BOOST_TEST(deque_t::get_block_size() == 64U);
+}
+
+int main()
+{
+ test_block_bytes();
+ test_block_elements();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/deque_test.cpp b/src/boost/libs/container/test/deque_test.cpp
new file mode 100644
index 000000000..22b87f49b
--- /dev/null
+++ b/src/boost/libs/container/test/deque_test.cpp
@@ -0,0 +1,446 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+#include <deque>
+#include <iostream>
+#include <list>
+
+#include <boost/container/deque.hpp>
+#include <boost/container/allocator.hpp>
+
+#include "print_container.hpp"
+#include "check_equal_containers.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <string>
+#include "emplace_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include <boost/core/no_exceptions_support.hpp>
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool deque_copyable_only(V1 &, V2 &, dtl::false_type)
+{
+ return true;
+}
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool deque_copyable_only(V1 &cntdeque, V2 &stddeque, dtl::true_type)
+{
+ typedef typename V1::value_type IntType;
+ std::size_t size = cntdeque.size();
+ stddeque.insert(stddeque.end(), 50, 1);
+ cntdeque.insert(cntdeque.end(), 50, IntType(1));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ {
+ IntType move_me(1);
+ stddeque.insert(stddeque.begin()+size/2, 50, 1);
+ cntdeque.insert(cntdeque.begin()+size/2, 50, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+ {
+ IntType move_me(2);
+ cntdeque.assign(cntdeque.size()/2, boost::move(move_me));
+ stddeque.assign(stddeque.size()/2, 2);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+ {
+ IntType move_me(1);
+ stddeque.clear();
+ cntdeque.clear();
+ stddeque.insert(stddeque.begin(), 50, 1);
+ cntdeque.insert(cntdeque.begin(), 50, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ stddeque.insert(stddeque.begin()+20, 50, 1);
+ cntdeque.insert(cntdeque.begin()+20, 50, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ stddeque.insert(stddeque.begin()+20, 20, 1);
+ cntdeque.insert(cntdeque.begin()+20, 20, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+ {
+ IntType move_me(1);
+ stddeque.clear();
+ cntdeque.clear();
+ stddeque.insert(stddeque.end(), 50, 1);
+ cntdeque.insert(cntdeque.end(), 50, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ stddeque.insert(stddeque.end()-20, 50, 1);
+ cntdeque.insert(cntdeque.end()-20, 50, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ stddeque.insert(stddeque.end()-20, 20, 1);
+ cntdeque.insert(cntdeque.end()-20, 20, boost::move(move_me));
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+
+ return true;
+}
+
+//Test recursive structures
+class recursive_deque
+{
+public:
+
+ recursive_deque & operator=(const recursive_deque &x)
+ { this->deque_ = x.deque_; return *this; }
+
+ int id_;
+ deque<recursive_deque> deque_;
+ deque<recursive_deque>::iterator it_;
+ deque<recursive_deque>::const_iterator cit_;
+ deque<recursive_deque>::reverse_iterator rit_;
+ deque<recursive_deque>::const_reverse_iterator crit_;
+};
+
+template<class IntType>
+bool do_test()
+{
+ //Test for recursive types
+ {
+ deque<recursive_deque> recursive_deque_deque;
+ }
+
+ {
+ //Now test move semantics
+ deque<recursive_deque> original;
+ deque<recursive_deque> move_ctor(boost::move(original));
+ deque<recursive_deque> move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+ }
+
+ //Alias deque types
+ typedef deque<IntType> MyCntDeque;
+ typedef std::deque<int> MyStdDeque;
+ const int max = 100;
+ {
+ ::boost::movelib::unique_ptr<MyCntDeque> const pcntdeque = ::boost::movelib::make_unique<MyCntDeque>();
+ ::boost::movelib::unique_ptr<MyStdDeque> const pstddeque = ::boost::movelib::make_unique<MyStdDeque>();
+ MyCntDeque &cntdeque = *pcntdeque;
+ MyStdDeque &stddeque = *pstddeque;
+ for(int i = 0; i < max*100; ++i){
+ IntType move_me(i);
+ cntdeque.insert(cntdeque.end(), boost::move(move_me));
+ stddeque.insert(stddeque.end(), i);
+ }
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ cntdeque.clear();
+ stddeque.clear();
+
+ for(int i = 0; i < max*100; ++i){
+ IntType move_me(i);
+ cntdeque.push_back(boost::move(move_me));
+ stddeque.push_back(i);
+ }
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ cntdeque.clear();
+ stddeque.clear();
+
+ for(int i = 0; i < max*100; ++i){
+ IntType move_me(i);
+ cntdeque.push_front(boost::move(move_me));
+ stddeque.push_front(i);
+ }
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ typename MyCntDeque::iterator it;
+ typename MyCntDeque::const_iterator cit = it;
+ (void)cit;
+
+ cntdeque.erase(cntdeque.begin()++);
+ stddeque.erase(stddeque.begin()++);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ cntdeque.erase(cntdeque.begin());
+ stddeque.erase(stddeque.begin());
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ {
+ //Initialize values
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me (-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+
+ cntdeque.insert(cntdeque.end()
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(aux_vect + 50));
+ stddeque.insert(stddeque.end(), aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ for(int i = 0; i < 50; ++i){
+ IntType move_me (i);
+ aux_vect[i] = boost::move(move_me);
+ }
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = i;
+ }
+
+ cntdeque.insert(cntdeque.begin()+cntdeque.size()
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(aux_vect + 50));
+ stddeque.insert(stddeque.begin()+stddeque.size(), aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ for(int i = 0, j = static_cast<int>(cntdeque.size()); i < j; ++i){
+ cntdeque.erase(cntdeque.begin());
+ stddeque.erase(stddeque.begin());
+ }
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ cntdeque.insert(cntdeque.begin()
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(aux_vect + 50));
+ stddeque.insert(stddeque.begin(), aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+ }
+
+ if(!deque_copyable_only(cntdeque, stddeque
+ ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+ return false;
+ }
+
+ cntdeque.erase(cntdeque.begin());
+ stddeque.erase(stddeque.begin());
+
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ for(int i = 0; i < max; ++i){
+ IntType move_me(i);
+ cntdeque.insert(cntdeque.begin(), boost::move(move_me));
+ stddeque.insert(stddeque.begin(), i);
+ }
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+ //Test insertion from list
+ {
+ std::list<int> l(50, int(1));
+ cntdeque.insert(cntdeque.begin(), l.begin(), l.end());
+ stddeque.insert(stddeque.begin(), l.begin(), l.end());
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+ cntdeque.assign(l.begin(), l.end());
+ stddeque.assign(l.begin(), l.end());
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+ }
+
+ cntdeque.resize(100);
+ stddeque.resize(100);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+
+ cntdeque.resize(200);
+ stddeque.resize(200);
+ if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+ }
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ //Check Constructor Template Auto Deduction
+ {
+ auto gold = MyStdDeque{ 1, 2, 3 };
+ auto test = deque(gold.begin(), gold.end());
+ if(!test::CheckEqualContainers(gold, test)) return false;
+ }
+ {
+ auto gold = MyStdDeque{ 1, 2, 3 };
+ auto test = deque(gold.begin(), gold.end(), new_allocator<int>());
+ if(!test::CheckEqualContainers(gold, test)) return false;
+ }
+#endif
+
+ std::cout << std::endl << "Test OK!" << std::endl;
+ return true;
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef deque< ValueType
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ > type;
+ };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+ if(test::vector_test<MyCont>())
+ return 1;
+ if(test::vector_test<MyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyCont>())
+ return 1;
+ return 0;
+}
+
+struct boost_container_deque;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_deque>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::deque<T, Allocator> type;
+ };
+};
+
+}}} //namespace boost::container::test
+
+int main ()
+{
+ if(!do_test<int>())
+ return 1;
+
+ if(!do_test<test::movable_int>())
+ return 1;
+
+ if(!do_test<test::movable_and_copyable_int>())
+ return 1;
+
+ if(!do_test<test::copyable_int>())
+ return 1;
+
+ //Test non-copy-move operations
+ {
+ deque<test::non_copymovable_int> d;
+ d.emplace_back();
+ d.emplace_front(1);
+ d.resize(10);
+ d.resize(1);
+ }
+
+ ////////////////////////////////////
+ // Allocator implementations
+ ////////////////////////////////////
+ // std:allocator
+ if(test_cont_variants< std::allocator<void> >()){
+ std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+ return 1;
+ }
+ // boost::container::allocator
+ if(test_cont_variants< allocator<void> >()){
+ std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
+ return 1;
+ }
+ ////////////////////////////////////
+ // Default init test
+ ////////////////////////////////////
+ if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
+
+ if(!boost::container::test::test_emplace
+ < deque<test::EmplaceInt>, Options>())
+ return 1;
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_deque>())
+ return 1;
+
+ ////////////////////////////////////
+ // Initializer lists testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+ < boost::container::deque<int> >()) {
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::deque<int> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::deque<int> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::deque<int, std::allocator<int> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/derived_from_memory_resource.hpp b/src/boost/libs/container/test/derived_from_memory_resource.hpp
new file mode 100644
index 000000000..a8097a783
--- /dev/null
+++ b/src/boost/libs/container/test/derived_from_memory_resource.hpp
@@ -0,0 +1,87 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
+#define BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
+
+#include <boost/container/pmr/memory_resource.hpp>
+
+class derived_from_memory_resource
+ : public boost::container::pmr::memory_resource
+{
+ public:
+ explicit derived_from_memory_resource(unsigned i = 0u)
+ : id(i)
+ {}
+
+ virtual ~derived_from_memory_resource()
+ { destructor_called = true; }
+
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+ {
+ do_allocate_called = true;
+ do_allocate_bytes = bytes;
+ do_allocate_alignment = alignment;
+ return do_allocate_return;
+ }
+
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+ {
+ do_deallocate_called = true;
+ do_deallocate_p = p;
+ do_deallocate_bytes = bytes;
+ do_deallocate_alignment = alignment;
+ }
+
+ virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
+ {
+ do_is_equal_called = true;
+ do_is_equal_other = &other;
+ return static_cast<const derived_from_memory_resource&>(other).id == this->id;
+ }
+
+ void reset()
+ {
+ destructor_called = false;
+
+ do_allocate_return = 0;
+ do_allocate_called = false;
+ do_allocate_bytes = 0u;
+ do_allocate_alignment = 0u;
+
+ do_deallocate_called = false;
+ do_deallocate_p = 0;
+ do_deallocate_bytes = 0u;
+ do_deallocate_alignment = 0u;
+
+ do_is_equal_called = false;
+ do_is_equal_other = 0;
+ }
+ //checkers
+ static bool destructor_called;
+
+ unsigned id;
+ void *do_allocate_return;
+ mutable bool do_allocate_called;
+ mutable std::size_t do_allocate_bytes;
+ mutable std::size_t do_allocate_alignment;
+
+ mutable bool do_deallocate_called;
+ mutable void *do_deallocate_p;
+ mutable std::size_t do_deallocate_bytes;
+ mutable std::size_t do_deallocate_alignment;
+
+ mutable bool do_is_equal_called;
+ mutable const boost::container::pmr::memory_resource *do_is_equal_other;
+};
+
+bool derived_from_memory_resource::destructor_called = false;
+
+#endif //#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
diff --git a/src/boost/libs/container/test/dummy_test_allocator.hpp b/src/boost/libs/container/test/dummy_test_allocator.hpp
new file mode 100644
index 000000000..024ab0e0e
--- /dev/null
+++ b/src/boost/libs/container/test/dummy_test_allocator.hpp
@@ -0,0 +1,232 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+#define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/assert.hpp>
+
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace test {
+
+//Very simple version 1 allocator
+template<class T>
+class simple_allocator
+{
+ public:
+ typedef T value_type;
+
+ simple_allocator()
+ {}
+
+ template<class U>
+ simple_allocator(const simple_allocator<U> &)
+ {}
+
+ T* allocate(std::size_t n)
+ { return (T*)::new char[sizeof(T)*n]; }
+
+ void deallocate(T*p, std::size_t)
+ { delete[] ((char*)p);}
+
+ friend bool operator==(const simple_allocator &, const simple_allocator &)
+ { return true; }
+
+ friend bool operator!=(const simple_allocator &, const simple_allocator &)
+ { return false; }
+};
+
+template< class T
+ , bool PropagateOnContCopyAssign
+ , bool PropagateOnContMoveAssign
+ , bool PropagateOnContSwap
+ , bool CopyOnPropagateOnContSwap
+ >
+class propagation_test_allocator
+{
+ BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+
+ public:
+ typedef T value_type;
+ typedef boost::container::dtl::bool_<PropagateOnContCopyAssign>
+ propagate_on_container_copy_assignment;
+ typedef boost::container::dtl::bool_<PropagateOnContMoveAssign>
+ propagate_on_container_move_assignment;
+ typedef boost::container::dtl::bool_<PropagateOnContSwap>
+ propagate_on_container_swap;
+
+ template<class T2>
+ struct rebind
+ { typedef propagation_test_allocator
+ < T2
+ , PropagateOnContCopyAssign
+ , PropagateOnContMoveAssign
+ , PropagateOnContSwap
+ , CopyOnPropagateOnContSwap> other;
+ };
+
+ propagation_test_allocator select_on_container_copy_construction() const
+ { return CopyOnPropagateOnContSwap ? propagation_test_allocator(*this) : propagation_test_allocator(); }
+
+ explicit propagation_test_allocator()
+ : id_(++unique_id_)
+ , ctr_copies_(0)
+ , ctr_moves_(0)
+ , assign_copies_(0)
+ , assign_moves_(0)
+ , swaps_(0)
+ {}
+
+ propagation_test_allocator(const propagation_test_allocator &x)
+ : id_(x.id_)
+ , ctr_copies_(x.ctr_copies_+1)
+ , ctr_moves_(x.ctr_moves_)
+ , assign_copies_(x.assign_copies_)
+ , assign_moves_(x.assign_moves_)
+ , swaps_(x.swaps_)
+ {}
+
+ template<class U>
+ propagation_test_allocator(const propagation_test_allocator
+ < U
+ , PropagateOnContCopyAssign
+ , PropagateOnContMoveAssign
+ , PropagateOnContSwap
+ , CopyOnPropagateOnContSwap> &x)
+ : id_(x.id_)
+ , ctr_copies_(x.ctr_copies_+1)
+ , ctr_moves_(0)
+ , assign_copies_(0)
+ , assign_moves_(0)
+ , swaps_(0)
+ {}
+
+ propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) x)
+ : id_(x.id_)
+ , ctr_copies_(x.ctr_copies_)
+ , ctr_moves_(x.ctr_moves_ + 1)
+ , assign_copies_(x.assign_copies_)
+ , assign_moves_(x.assign_moves_)
+ , swaps_(x.swaps_)
+ {}
+
+ propagation_test_allocator &operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator) x)
+ {
+ id_ = x.id_;
+ ctr_copies_ = x.ctr_copies_;
+ ctr_moves_ = x.ctr_moves_;
+ assign_copies_ = x.assign_copies_+1;
+ assign_moves_ = x.assign_moves_;
+ swaps_ = x.swaps_;
+ return *this;
+ }
+
+ propagation_test_allocator &operator=(BOOST_RV_REF(propagation_test_allocator) x)
+ {
+ id_ = x.id_;
+ ctr_copies_ = x.ctr_copies_;
+ ctr_moves_ = x.ctr_moves_;
+ assign_copies_ = x.assign_copies_;
+ assign_moves_ = x.assign_moves_+1;
+ swaps_ = x.swaps_;
+ return *this;
+ }
+
+ static void reset_unique_id(unsigned id = 0)
+ { unique_id_ = id; }
+
+ T* allocate(std::size_t n)
+ { return (T*)::new char[sizeof(T)*n]; }
+
+ void deallocate(T*p, std::size_t)
+ { delete[] ((char*)p);}
+
+ friend bool operator==(const propagation_test_allocator &, const propagation_test_allocator &)
+ { return true; }
+
+ friend bool operator!=(const propagation_test_allocator &, const propagation_test_allocator &)
+ { return false; }
+
+ void swap(propagation_test_allocator &r)
+ {
+ ++this->swaps_; ++r.swaps_;
+ boost::adl_move_swap(this->id_, r.id_);
+ boost::adl_move_swap(this->ctr_copies_, r.ctr_copies_);
+ boost::adl_move_swap(this->ctr_moves_, r.ctr_moves_);
+ boost::adl_move_swap(this->assign_copies_, r.assign_copies_);
+ boost::adl_move_swap(this->assign_moves_, r.assign_moves_);
+ boost::adl_move_swap(this->swaps_, r.swaps_);
+ }
+
+ friend void swap(propagation_test_allocator &l, propagation_test_allocator &r)
+ {
+ l.swap(r);
+ }
+
+ unsigned int id_;
+ unsigned int ctr_copies_;
+ unsigned int ctr_moves_;
+ unsigned int assign_copies_;
+ unsigned int assign_moves_;
+ unsigned int swaps_;
+ static unsigned unique_id_;
+};
+
+template< class T
+ , bool PropagateOnContCopyAssign
+ , bool PropagateOnContMoveAssign
+ , bool PropagateOnContSwap
+ , bool CopyOnPropagateOnContSwap
+ >
+unsigned int propagation_test_allocator< T
+ , PropagateOnContCopyAssign
+ , PropagateOnContMoveAssign
+ , PropagateOnContSwap
+ , CopyOnPropagateOnContSwap>::unique_id_ = 0;
+
+
+} //namespace test {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+
diff --git a/src/boost/libs/container/test/emplace_test.hpp b/src/boost/libs/container/test/emplace_test.hpp
new file mode 100644
index 000000000..f017d9550
--- /dev/null
+++ b/src/boost/libs/container/test/emplace_test.hpp
@@ -0,0 +1,686 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
+#define BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
+
+#include <iostream>
+#include <typeinfo>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+class EmplaceInt
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt)
+
+ public:
+ EmplaceInt(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0)
+ : a_(a), b_(b), c_(c), d_(d), e_(e)
+ {}
+
+ EmplaceInt(BOOST_RV_REF(EmplaceInt) o)
+ : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_)
+ {}
+
+ EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o)
+ {
+ this->a_ = o.a_;
+ this->b_ = o.b_;
+ this->c_ = o.c_;
+ this->d_ = o.d_;
+ this->e_ = o.e_;
+ return *this;
+ }
+
+ friend bool operator==(const EmplaceInt &l, const EmplaceInt &r)
+ {
+ return l.a_ == r.a_ &&
+ l.b_ == r.b_ &&
+ l.c_ == r.c_ &&
+ l.d_ == r.d_ &&
+ l.e_ == r.e_;
+ }
+
+ friend bool operator<(const EmplaceInt &l, const EmplaceInt &r)
+ { return l.sum() < r.sum(); }
+
+ friend bool operator>(const EmplaceInt &l, const EmplaceInt &r)
+ { return l.sum() > r.sum(); }
+
+ friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r)
+ { return !(l == r); }
+
+ friend std::size_t hash_value(const EmplaceInt &v)
+ { return std::size_t(v.a_); }
+
+ friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v)
+ {
+ os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_;
+ return os;
+ }
+
+ ~EmplaceInt()
+ { a_ = b_ = c_ = d_ = e_ = 0; }
+
+ //private:
+ int sum() const
+ { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; }
+
+ int a_, b_, c_, d_, e_;
+ int padding[6];
+};
+
+
+} //namespace test {
+
+namespace test {
+
+enum EmplaceOptions{
+ EMPLACE_BACK = 1 << 0,
+ EMPLACE_FRONT = 1 << 1,
+ EMPLACE_BEFORE = 1 << 2,
+ EMPLACE_AFTER = 1 << 3,
+ EMPLACE_ASSOC = 1 << 4,
+ EMPLACE_HINT = 1 << 5,
+ EMPLACE_ASSOC_PAIR = 1 << 6,
+ EMPLACE_HINT_PAIR = 1 << 7
+};
+
+template<class Container>
+bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n, unsigned int cont_offset = 0)
+{
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator itb(ec.begin()), ite(ec.end());
+ unsigned int cur = 0;
+ if(cont_offset > ec.size()){
+ return false;
+ }
+ if(only_first_n > (ec.size() - cont_offset)){
+ return false;
+ }
+ while(cont_offset--){
+ ++itb;
+ }
+ for(; itb != ite && only_first_n--; ++itb, ++cur){
+ const EmplaceInt & cr = *itb;
+ if(cr != Expected[cur]){
+ return false;
+ }
+ }
+ return true;
+}
+
+template<class Container>
+bool test_expected_container(const Container &ec, const std::pair<EmplaceInt, EmplaceInt> *Expected, unsigned int only_first_n)
+{
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator itb(ec.begin()), ite(ec.end());
+ unsigned int cur = 0;
+ if(only_first_n > ec.size()){
+ return false;
+ }
+ for(; itb != ite && only_first_n--; ++itb, ++cur){
+ if(itb->first != Expected[cur].first){
+ std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl;
+ return false;
+
+ }
+ else if(itb->second != Expected[cur].second){
+ std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+typedef std::pair<EmplaceInt, EmplaceInt> EmplaceIntPair;
+static boost::container::dtl::aligned_storage<sizeof(EmplaceIntPair)*10>::type pair_storage;
+
+static EmplaceIntPair* initialize_emplace_int_pair()
+{
+ EmplaceIntPair* ret = reinterpret_cast<EmplaceIntPair*>(&pair_storage);
+ for(unsigned int i = 0; i != 10; ++i){
+ new(&ret->first)EmplaceInt();
+ new(&ret->second)EmplaceInt();
+ }
+ return ret;
+}
+
+static EmplaceIntPair * expected_pair = initialize_emplace_int_pair();
+
+
+template<class Container>
+bool test_emplace_back(dtl::true_)
+{
+ std::cout << "Starting test_emplace_back." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+
+ {
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt(1, 2);
+ new(&expected [3]) EmplaceInt(1, 2, 3);
+ new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+ Container c;
+ typedef typename Container::reference reference;
+ {
+ reference r = c.emplace_back();
+ if(&r != &c.back() && !test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ }
+ {
+ reference r = c.emplace_back(1);
+ if(&r != &c.back() && !test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ }
+ c.emplace_back(1, 2);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ c.emplace_back(1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 4)){
+ return false;
+ }
+ c.emplace_back(1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 5)){
+ return false;
+ }
+ c.emplace_back(1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ }
+ std::cout << "...OK" << std::endl;
+ return true;
+}
+
+template<class Container>
+bool test_emplace_back(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_front(dtl::true_)
+{
+ std::cout << "Starting test_emplace_front." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+ {
+ new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5);
+ new(&expected [1]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [2]) EmplaceInt(1, 2, 3);
+ new(&expected [3]) EmplaceInt(1, 2);
+ new(&expected [4]) EmplaceInt(1);
+ new(&expected [5]) EmplaceInt();
+ Container c;
+ typedef typename Container::reference reference;
+ {
+ reference r = c.emplace_front();
+ if(&r != &c.front() && !test_expected_container(c, &expected[0] + 5, 1)){
+ return false;
+ }
+ }
+ {
+ reference r = c.emplace_front(1);
+ if(&r != &c.front() && !test_expected_container(c, &expected[0] + 4, 2)){
+ return false;
+ }
+ }
+ c.emplace_front(1, 2);
+ if(!test_expected_container(c, &expected[0] + 3, 3)){
+ return false;
+ }
+ c.emplace_front(1, 2, 3);
+ if(!test_expected_container(c, &expected[0] + 2, 4)){
+ return false;
+ }
+ c.emplace_front(1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0] + 1, 5)){
+ return false;
+ }
+ c.emplace_front(1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0] + 0, 6)){
+ return false;
+ }
+ }
+ std::cout << "...OK" << std::endl;
+ return true;
+}
+
+template<class Container>
+bool test_emplace_front(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_before(dtl::true_)
+{
+ std::cout << "Starting test_emplace_before." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+ {
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt();
+ Container c;
+ c.emplace(c.cend(), 1);
+ c.emplace(c.cbegin());
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ c.emplace(c.cend());
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ }
+ {
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt(1, 2);
+ new(&expected [3]) EmplaceInt(1, 2, 3);
+ new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+ //emplace_front-like
+ Container c;
+ c.emplace(c.cbegin(), 1, 2, 3, 4, 5);
+ c.emplace(c.cbegin(), 1, 2, 3, 4);
+ c.emplace(c.cbegin(), 1, 2, 3);
+ c.emplace(c.cbegin(), 1, 2);
+ c.emplace(c.cbegin(), 1);
+ c.emplace(c.cbegin());
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ c.clear();
+ //emplace_back-like
+ typename Container::const_iterator i = c.emplace(c.cend());
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ i = c.emplace(++i, 1);
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ i = c.emplace(++i, 1, 2);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ i = c.emplace(++i, 1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 4)){
+ return false;
+ }
+ i = c.emplace(++i, 1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 5)){
+ return false;
+ }
+ i = c.emplace(++i, 1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ c.clear();
+ //emplace in the middle
+ c.emplace(c.cbegin());
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ i = c.emplace(c.cend(), 1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ if(!test_expected_container(c, &expected[5], 1, 1)){
+ return false;
+ }
+ i = c.emplace(i, 1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ if(!test_expected_container(c, &expected[4], 2, 1)){
+ return false;
+ }
+ i = c.emplace(i, 1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ if(!test_expected_container(c, &expected[3], 3, 1)){
+ return false;
+ }
+ i = c.emplace(i, 1, 2);
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ if(!test_expected_container(c, &expected[2], 4, 1)){
+ return false;
+ }
+ i = c.emplace(i, 1);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+ return true;
+}
+
+template<class Container>
+bool test_emplace_before(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_after(dtl::true_)
+{
+ std::cout << "Starting test_emplace_after." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+ {
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt();
+ Container c;
+ typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1);
+ c.emplace_after(c.cbefore_begin());
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ c.emplace_after(i);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ }
+ {
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt(1, 2);
+ new(&expected [3]) EmplaceInt(1, 2, 3);
+ new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+ //emplace_front-like
+ Container c;
+ c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5);
+ c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4);
+ c.emplace_after(c.cbefore_begin(), 1, 2, 3);
+ c.emplace_after(c.cbefore_begin(), 1, 2);
+ c.emplace_after(c.cbefore_begin(), 1);
+ c.emplace_after(c.cbefore_begin());
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ c.clear();
+ //emplace_back-like
+ typename Container::const_iterator i = c.emplace_after(c.cbefore_begin());
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ i = c.emplace_after(i, 1);
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ i = c.emplace_after(i, 1, 2);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ i = c.emplace_after(i, 1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 4)){
+ return false;
+ }
+ i = c.emplace_after(i, 1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 5)){
+ return false;
+ }
+ i = c.emplace_after(i, 1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ c.clear();
+ //emplace_after in the middle
+ i = c.emplace_after(c.cbefore_begin());
+ c.emplace_after(i, 1, 2, 3, 4, 5);
+ c.emplace_after(i, 1, 2, 3, 4);
+ c.emplace_after(i, 1, 2, 3);
+ c.emplace_after(i, 1, 2);
+ c.emplace_after(i, 1);
+
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+ return true;
+}
+
+template<class Container>
+bool test_emplace_after(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_assoc(dtl::true_)
+{
+ std::cout << "Starting test_emplace_assoc." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt(1, 2);
+ new(&expected [3]) EmplaceInt(1, 2, 3);
+ new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+ {
+ Container c;
+ c.emplace();
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ c.emplace(1);
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ c.emplace(1, 2);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ c.emplace(1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 4)){
+ return false;
+ }
+ c.emplace(1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 5)){
+ return false;
+ }
+ c.emplace(1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+ return true;
+}
+
+template<class Container>
+bool test_emplace_assoc(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_hint(dtl::true_)
+{
+ std::cout << "Starting test_emplace_hint." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+ static EmplaceInt expected [10];
+ new(&expected [0]) EmplaceInt();
+ new(&expected [1]) EmplaceInt(1);
+ new(&expected [2]) EmplaceInt(1, 2);
+ new(&expected [3]) EmplaceInt(1, 2, 3);
+ new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+ new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+
+ {
+ Container c;
+ typename Container::const_iterator it;
+ it = c.emplace_hint(c.begin());
+ if(!test_expected_container(c, &expected[0], 1)){
+ return false;
+ }
+ it = c.emplace_hint(it, 1);
+ if(!test_expected_container(c, &expected[0], 2)){
+ return false;
+ }
+ it = c.emplace_hint(it, 1, 2);
+ if(!test_expected_container(c, &expected[0], 3)){
+ return false;
+ }
+ it = c.emplace_hint(it, 1, 2, 3);
+ if(!test_expected_container(c, &expected[0], 4)){
+ return false;
+ }
+ it = c.emplace_hint(it, 1, 2, 3, 4);
+ if(!test_expected_container(c, &expected[0], 5)){
+ return false;
+ }
+ it = c.emplace_hint(it, 1, 2, 3, 4, 5);
+ if(!test_expected_container(c, &expected[0], 6)){
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+
+ return true;
+}
+
+template<class Container>
+bool test_emplace_hint(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_assoc_pair(dtl::true_)
+{
+ std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+
+ new(&expected_pair[0].first) EmplaceInt();
+ new(&expected_pair[0].second) EmplaceInt();
+ new(&expected_pair[1].first) EmplaceInt(1);
+ new(&expected_pair[1].second) EmplaceInt(1);
+ new(&expected_pair[2].first) EmplaceInt(2);
+ new(&expected_pair[2].second) EmplaceInt(2);
+ {
+ Container c;
+ c.emplace();
+ if(!test_expected_container(c, &expected_pair[0], 1)){
+ std::cout << "Error after c.emplace();\n";
+ return false;
+ }
+ c.emplace(1, 1);
+ if(!test_expected_container(c, &expected_pair[0], 2)){
+ std::cout << "Error after c.emplace(1);\n";
+ return false;
+ }
+ c.emplace(2, 2);
+ if(!test_expected_container(c, &expected_pair[0], 3)){
+ std::cout << "Error after c.emplace(2, 2);\n";
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+ return true;
+}
+
+template<class Container>
+bool test_emplace_assoc_pair(dtl::false_)
+{ return true; }
+
+template<class Container>
+bool test_emplace_hint_pair(dtl::true_)
+{
+ std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: "
+ << typeid(Container).name() << std::endl;
+
+ new(&expected_pair[0].first) EmplaceInt();
+ new(&expected_pair[0].second) EmplaceInt();
+ new(&expected_pair[1].first) EmplaceInt(1);
+ new(&expected_pair[1].second) EmplaceInt(1);
+ new(&expected_pair[2].first) EmplaceInt(2);
+ new(&expected_pair[2].second) EmplaceInt(2);
+ {
+ Container c;
+ typename Container::const_iterator it;
+ it = c.emplace_hint(c.begin());
+ if(!test_expected_container(c, &expected_pair[0], 1)){
+ std::cout << "Error after c.emplace(1);\n";
+ return false;
+ }
+ it = c.emplace_hint(it, 1, 1);
+ if(!test_expected_container(c, &expected_pair[0], 2)){
+ std::cout << "Error after c.emplace(it, 1);\n";
+ return false;
+ }
+ it = c.emplace_hint(it, 2, 2);
+ if(!test_expected_container(c, &expected_pair[0], 3)){
+ std::cout << "Error after c.emplace(it, 2, 2);\n";
+ return false;
+ }
+ std::cout << "...OK" << std::endl;
+ }
+ return true;
+}
+
+template<class Container>
+bool test_emplace_hint_pair(dtl::false_)
+{ return true; }
+
+template <EmplaceOptions O, EmplaceOptions Mask>
+struct emplace_active
+{
+ static const bool value = (0 != (O & Mask));
+ typedef dtl::bool_<value> type;
+ operator type() const{ return type(); }
+};
+
+template<class Container, EmplaceOptions O>
+bool test_emplace()
+{
+ if(!test_emplace_back<Container>(emplace_active<O, EMPLACE_BACK>())){
+ return false;
+ }
+ if(!test_emplace_front<Container>(emplace_active<O, EMPLACE_FRONT>())){
+ return false;
+ }
+ if(!test_emplace_before<Container>(emplace_active<O, EMPLACE_BEFORE>())){
+ return false;
+ }
+ if(!test_emplace_after<Container>(emplace_active<O, EMPLACE_AFTER>())){
+ return false;
+ }
+ if(!test_emplace_assoc<Container>(emplace_active<O, EMPLACE_ASSOC>())){
+ return false;
+ }
+ if(!test_emplace_hint<Container>(emplace_active<O, EMPLACE_HINT>())){
+ return false;
+ }
+ if(!test_emplace_assoc_pair<Container>(emplace_active<O, EMPLACE_ASSOC_PAIR>())){
+ return false;
+ }
+ if(!test_emplace_hint_pair<Container>(emplace_active<O, EMPLACE_HINT_PAIR>())){
+ return false;
+ }
+ return true;
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
diff --git a/src/boost/libs/container/test/expand_bwd_test_allocator.hpp b/src/boost/libs/container/test/expand_bwd_test_allocator.hpp
new file mode 100644
index 000000000..60b32839e
--- /dev/null
+++ b/src/boost/libs/container/test/expand_bwd_test_allocator.hpp
@@ -0,0 +1,200 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. 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/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+#define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/assert.hpp>
+
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace test {
+
+//This allocator just allows two allocations. The first one will return
+//mp_buffer + m_offset configured in the constructor. The second one
+//will return mp_buffer.
+template<class T>
+class expand_bwd_test_allocator
+{
+ private:
+ typedef expand_bwd_test_allocator<T> self_t;
+ typedef void * aux_pointer_t;
+ typedef const void * cvoid_ptr;
+
+ template<class T2>
+ expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator<T2>&);
+
+ expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&);
+
+ public:
+ typedef T value_type;
+ typedef T * pointer;
+ typedef const T * const_pointer;
+ typedef typename dtl::add_reference
+ <value_type>::type reference;
+ typedef typename dtl::add_reference
+ <const value_type>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::dtl::version_type<expand_bwd_test_allocator, 2> version;
+
+ //Dummy multiallocation chain
+ struct multiallocation_chain{};
+
+ template<class T2>
+ struct rebind
+ { typedef expand_bwd_test_allocator<T2> other; };
+
+ //!Constructor from the segment manager. Never throws
+ expand_bwd_test_allocator(T *buffer, size_type sz, difference_type offset)
+ : mp_buffer(buffer), m_size(sz)
+ , m_offset(offset), m_allocations(0){ }
+
+ //!Constructor from other expand_bwd_test_allocator. Never throws
+ expand_bwd_test_allocator(const expand_bwd_test_allocator &other)
+ : mp_buffer(other.mp_buffer), m_size(other.m_size)
+ , m_offset(other.m_offset), m_allocations(0){ }
+
+ //!Constructor from related expand_bwd_test_allocator. Never throws
+ template<class T2>
+ expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other)
+ : mp_buffer(other.mp_buffer), m_size(other.m_size)
+ , m_offset(other.m_offset), m_allocations(0){ }
+
+ pointer address(reference value)
+ { return pointer(dtl::addressof(value)); }
+
+ const_pointer address(const_reference value) const
+ { return const_pointer(dtl::addressof(value)); }
+
+ pointer allocate(size_type , cvoid_ptr hint = 0)
+ { (void)hint; return 0; }
+
+ void deallocate(const pointer &, size_type)
+ {}
+
+ template<class Convertible>
+ void construct(pointer ptr, const Convertible &value)
+ { new((void*)ptr) value_type(value); }
+
+ void destroy(pointer ptr)
+ { (*ptr).~value_type(); }
+
+ size_type max_size() const
+ { return m_size; }
+
+ friend void swap(self_t &alloc1, self_t &alloc2)
+ {
+ boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer);
+ boost::adl_move_swap(alloc1.m_size, alloc2.m_size);
+ boost::adl_move_swap(alloc1.m_offset, alloc2.m_offset);
+ }
+
+ //Experimental version 2 expand_bwd_test_allocator functions
+
+ pointer allocation_command(boost::container::allocation_type command,
+ size_type limit_size,size_type &prefer_in_recvd_out_size,pointer &reuse)
+ {
+ (void)reuse; (void)command;
+ //This allocator only expands backwards!
+ assert(m_allocations == 0 || (command & boost::container::expand_bwd));
+
+ prefer_in_recvd_out_size = limit_size;
+
+ if(m_allocations == 0){
+ if((m_offset + limit_size) > m_size){
+ assert(0);
+ }
+ ++m_allocations;
+ reuse = 0;
+ return (mp_buffer + m_offset);
+ }
+ else if(m_allocations == 1){
+ if(limit_size > m_size){
+ assert(0);
+ }
+ ++m_allocations;
+ return mp_buffer;
+ }
+ else{
+ throw_bad_alloc();
+ return mp_buffer;
+ }
+ }
+
+ //!Returns maximum the number of objects the previously allocated memory
+ //!pointed by p can hold.
+ size_type size(const pointer &p) const
+ { (void)p; return m_size; }
+
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws boost::container::bad_alloc if there is no enough memory
+ pointer allocate_one()
+ { return this->allocate(1); }
+
+ //!Deallocates memory previously allocated with allocate_one().
+ //!You should never use deallocate_one to deallocate memory allocated
+ //!with other functions different from allocate_one(). Never throws
+ void deallocate_one(const pointer &p)
+ { return this->deallocate(p, 1); }
+
+ pointer mp_buffer;
+ size_type m_size;
+ difference_type m_offset;
+ char m_allocations;
+};
+
+//!Equality test for same type of expand_bwd_test_allocator
+template<class T> inline
+bool operator==(const expand_bwd_test_allocator<T> &,
+ const expand_bwd_test_allocator<T> &)
+{ return false; }
+
+//!Inequality test for same type of expand_bwd_test_allocator
+template<class T> inline
+bool operator!=(const expand_bwd_test_allocator<T> &,
+ const expand_bwd_test_allocator<T> &)
+{ return true; }
+
+} //namespace test {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+
diff --git a/src/boost/libs/container/test/expand_bwd_test_template.hpp b/src/boost/libs/container/test/expand_bwd_test_template.hpp
new file mode 100644
index 000000000..1c193ac66
--- /dev/null
+++ b/src/boost/libs/container/test/expand_bwd_test_template.hpp
@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
+#define BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <vector>
+#include <typeinfo>
+#include <iostream>
+#include "expand_bwd_test_allocator.hpp"
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include "movable_int.hpp"
+#include <boost/move/make_unique.hpp>
+
+namespace boost { namespace container { namespace test {
+
+//Function to check if both sets are equal
+template <class Vector1, class Vector2>
+bool CheckEqualVector(const Vector1 &vector1, const Vector2 &vector2)
+{
+ if(vector1.size() != vector2.size())
+ return false;
+ return boost::container::algo_equal(vector1.begin(), vector1.end(), vector2.begin());
+}
+
+template<class Vector>
+bool CheckUninitializedIsZero(const Vector & v)
+{
+ typedef typename Vector::value_type value_type;
+ typename Vector::size_type sz = v.size();
+ typename Vector::size_type extra = v.capacity() - v.size();
+ value_type comp(0);
+
+ const value_type *holder = &v[0] + sz;
+
+ while(extra--){
+ if(*holder++ != comp)
+ return false;
+ }
+ return true;
+}
+
+
+//This function tests all the possible combinations when
+//inserting data in a vector and expanding backwards
+template<class VectorWithExpandBwdAllocator>
+bool test_insert_with_expand_bwd()
+{
+ typedef typename VectorWithExpandBwdAllocator::value_type value_type;
+ typedef std::vector<value_type> Vect;
+ const unsigned int MemorySize = 1000;
+
+ //Distance old and new buffer
+ const unsigned int Offset[] =
+ { 350, 300, 250, 200, 150, 100, 150, 100,
+ 150, 50, 50, 50 };
+ //Initial vector size
+ const unsigned int InitialSize[] =
+ { 200, 200, 200, 200, 200, 200, 200, 200,
+ 200, 200, 200, 200 };
+ //Size of the data to insert
+ const unsigned int InsertSize[] =
+ { 100, 100, 100, 100, 100, 100, 200, 200,
+ 300, 25, 100, 200 };
+ //Number of tests
+ const unsigned int Iterations = sizeof(InsertSize)/sizeof(int);
+
+ //Insert position
+ const int Position[] =
+ { 0, 100, 200 };
+
+ for(unsigned int pos = 0; pos < sizeof(Position)/sizeof(Position[0]); ++pos){
+ if(!life_count<value_type>::check(0))
+ return false;
+
+ for(unsigned int iteration = 0; iteration < Iterations; ++iteration)
+ {
+ boost::movelib::unique_ptr<char[]> memptr =
+ boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
+ value_type *memory = (value_type*)memptr.get();
+ std::vector<value_type> initial_data;
+ initial_data.resize(InitialSize[iteration]);
+ for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
+ initial_data[i] = i;
+ }
+
+ if(!life_count<value_type>::check(InitialSize[iteration]))
+ return false;
+ Vect data_to_insert;
+ data_to_insert.resize(InsertSize[iteration]);
+ for(unsigned int i = 0; i < InsertSize[iteration]; ++i){
+ data_to_insert[i] = -i;
+ }
+
+ if(!life_count<value_type>::check(InitialSize[iteration]+InsertSize[iteration]))
+ return false;
+
+ expand_bwd_test_allocator<value_type> alloc
+ (memory, MemorySize, Offset[iteration]);
+ VectorWithExpandBwdAllocator vector(alloc);
+ vector.insert( vector.begin()
+ , initial_data.begin(), initial_data.end());
+ vector.insert( vector.begin() + Position[pos]
+ , data_to_insert.begin(), data_to_insert.end());
+
+ if(!life_count<value_type>::check(InitialSize[iteration]*2+InsertSize[iteration]*2))
+ return false;
+
+ initial_data.insert(initial_data.begin() + Position[pos]
+ , data_to_insert.begin(), data_to_insert.end());
+ //Now check that values are equal
+ if(!CheckEqualVector(vector, initial_data)){
+ std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+ << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+ << " Iteration: " << iteration << std::endl;
+ return false;
+ }
+ }
+ if(!life_count<value_type>::check(0))
+ return false;
+ }
+
+ return true;
+}
+
+//This function tests all the possible combinations when
+//inserting data in a vector and expanding backwards
+template<class VectorWithExpandBwdAllocator>
+bool test_assign_with_expand_bwd()
+{
+ typedef typename VectorWithExpandBwdAllocator::value_type value_type;
+ const unsigned int MemorySize = 200;
+
+ const unsigned int Offset[] = { 50, 50, 50};
+ const unsigned int InitialSize[] = { 25, 25, 25};
+ const unsigned int InsertSize[] = { 15, 35, 55};
+ const unsigned int Iterations = sizeof(InsertSize)/sizeof(int);
+
+ for(unsigned int iteration = 0; iteration <Iterations; ++iteration)
+ {
+ boost::movelib::unique_ptr<char[]> memptr =
+ boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
+ value_type *memory = (value_type*)memptr.get();
+ //Create initial data
+ std::vector<value_type> initial_data;
+ initial_data.resize(InitialSize[iteration]);
+ for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
+ initial_data[i] = i;
+ }
+
+ //Create data to assign
+ std::vector<value_type> data_to_insert;
+ data_to_insert.resize(InsertSize[iteration]);
+ for(unsigned int i = 0; i < InsertSize[iteration]; ++i){
+ data_to_insert[i] = -i;
+ }
+
+ //Insert initial data to the vector to test
+ expand_bwd_test_allocator<value_type> alloc
+ (memory, MemorySize, Offset[iteration]);
+ VectorWithExpandBwdAllocator vector(alloc);
+ vector.insert( vector.begin()
+ , initial_data.begin(), initial_data.end());
+
+ //Assign data
+ vector.insert(vector.cbegin(), data_to_insert.begin(), data_to_insert.end());
+ initial_data.insert(initial_data.begin(), data_to_insert.begin(), data_to_insert.end());
+
+ //Now check that values are equal
+ if(!CheckEqualVector(vector, initial_data)){
+ std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+ << " Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+ << " Iteration: " << iteration << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//This function calls all tests
+template<class VectorWithExpandBwdAllocator>
+bool test_all_expand_bwd()
+{
+ std::cout << "Starting test_insert_with_expand_bwd." << std::endl << " Class: "
+ << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+
+ if(!test_insert_with_expand_bwd<VectorWithExpandBwdAllocator>()){
+ std::cout << "test_allocation_direct_deallocation failed. Class: "
+ << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+ return false;
+ }
+
+ std::cout << "Starting test_assign_with_expand_bwd." << std::endl << " Class: "
+ << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+
+ if(!test_assign_with_expand_bwd<VectorWithExpandBwdAllocator>()){
+ std::cout << "test_allocation_direct_deallocation failed. Class: "
+ << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+}}} //namespace boost { namespace container { namespace test {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
diff --git a/src/boost/libs/container/test/explicit_inst_deque_test.cpp b/src/boost/libs/container/test/explicit_inst_deque_test.cpp
new file mode 100644
index 000000000..6fec8116b
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_deque_test.cpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/deque.hpp>
+#include <boost/container/allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::deque<empty>;
+
+volatile ::boost::container::deque<empty> dummy;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::deque
+ < test::movable_and_copyable_int
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::deque
+ < test::movable_and_copyable_int
+ , allocator<test::movable_and_copyable_int> >;
+
+} //namespace boost {
+} //namespace container {
+
+int main()
+{
+ return 0;
+}
+
diff --git a/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp b/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp
new file mode 100644
index 000000000..3a8ff6fa3
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp
@@ -0,0 +1,94 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/flat_map.hpp>
+#include <boost/container/allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/static_vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::flat_map<empty, empty>;
+template class ::boost::container::flat_multimap<empty, empty>;
+
+volatile ::boost::container::flat_map<empty, empty> dummy;
+volatile ::boost::container::flat_multimap<empty, empty> dummy2;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//flat_map
+typedef std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> test_pair_t;
+
+template class flat_map
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , small_vector< test_pair_t, 10, std::allocator< test_pair_t > >
+ >;
+
+//flat_multimap
+template class flat_multimap
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , stable_vector< test_pair_t, allocator< test_pair_t > >
+ >;
+
+template class flat_multimap
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , deque<test_pair_t, test::simple_allocator< test_pair_t > >
+ >;
+
+template class flat_multimap
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , static_vector<test_pair_t, 10 >
+ >;
+
+//As flat container iterators are typedefs for vector::[const_]iterator,
+//no need to explicit instantiate them
+
+}} //boost::container
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+
+template class flat_map
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , std::vector<test_pair_t>
+>;
+
+}} //boost::container
+
+#endif
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp b/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp
new file mode 100644
index 000000000..eeb8366ed
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp
@@ -0,0 +1,88 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/flat_set.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::flat_set<empty>;
+template class ::boost::container::flat_multiset<empty>;
+
+volatile ::boost::container::flat_set<empty> dummy;
+volatile ::boost::container::flat_multiset<empty> dummy2;
+
+#include <boost/container/allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/static_vector.hpp>
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//flat_set
+template class flat_set
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , small_vector<test::movable_and_copyable_int, 10, allocator<test::movable_and_copyable_int> >
+ >;
+
+//flat_multiset
+template class flat_multiset
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , stable_vector<test::movable_and_copyable_int, test::simple_allocator<test::movable_and_copyable_int> >
+ >;
+
+template class flat_multiset
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , deque<test::movable_and_copyable_int, test::simple_allocator< test::movable_and_copyable_int > >
+ >;
+
+template class flat_multiset
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , static_vector<test::movable_and_copyable_int, 10 >
+ >;
+
+//As flat container iterators are typedefs for vector::[const_]iterator,
+//no need to explicit instantiate them
+
+}} //boost::container
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+
+template class flat_set
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , std::vector<test::movable_and_copyable_int>
+>;
+
+}} //boost::container
+
+#endif
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_list_test.cpp b/src/boost/libs/container/test/explicit_inst_list_test.cpp
new file mode 100644
index 000000000..4faeaebae
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_list_test.cpp
@@ -0,0 +1,25 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/list.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::list<empty>;
+
+int main()
+{
+ ::boost::container::list<empty> dummy;
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_map_test.cpp b/src/boost/libs/container/test/explicit_inst_map_test.cpp
new file mode 100644
index 000000000..5a4a2b408
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_map_test.cpp
@@ -0,0 +1,56 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/map.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::map<empty, empty>;
+template class ::boost::container::multimap<empty, empty>;
+
+volatile ::boost::container::map<empty, empty> dummy;
+volatile ::boost::container::multimap<empty, empty> dummy2;
+
+#include <boost/container/allocator.hpp>
+#include <boost/container/adaptive_pool.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+//Explicit instantiation to detect compilation errors
+
+//map
+template class map
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator< pair_t >
+ >;
+
+template class map
+ < test::movable_and_copyable_int
+ , test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , adaptive_pool< pair_t >
+ >;
+}} //boost::container
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_set_test.cpp b/src/boost/libs/container/test/explicit_inst_set_test.cpp
new file mode 100644
index 000000000..fa0312356
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_set_test.cpp
@@ -0,0 +1,54 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/set.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::set<empty>;
+template class ::boost::container::multiset<empty>;
+
+volatile ::boost::container::set<empty> dummy;
+volatile ::boost::container::multiset<empty> dummy2;
+
+#include <boost/container/allocator.hpp>
+#include <boost/container/adaptive_pool.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//set
+template class set
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator<test::movable_and_copyable_int>
+ >;
+
+//multiset
+template class multiset
+ < test::movable_and_copyable_int
+ , std::less<test::movable_and_copyable_int>
+ , adaptive_pool<test::movable_and_copyable_int>
+ >;
+
+}} //boost::container
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_slist_test.cpp b/src/boost/libs/container/test/explicit_inst_slist_test.cpp
new file mode 100644
index 000000000..f825c10c7
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_slist_test.cpp
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/slist.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::slist<empty>;
+volatile ::boost::container::slist<empty> dummy;
+
+#include <boost/container/allocator.hpp>
+#include <boost/container/node_allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::slist
+ < test::movable_and_copyable_int
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::slist
+ < test::movable_and_copyable_int
+ , node_allocator<test::movable_and_copyable_int> >;
+
+}}
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp
new file mode 100644
index 000000000..6259aae82
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp
@@ -0,0 +1,56 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/small_vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::small_vector<empty, 2>;
+volatile ::boost::container::small_vector<empty, 2> dummy;
+
+#include <boost/container/allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+template class small_vector<char, 0>;
+template class small_vector<char, 1>;
+template class small_vector<char, 2>;
+template class small_vector<char, 10>;
+
+template class small_vector<int, 0>;
+template class small_vector<int, 1>;
+template class small_vector<int, 2>;
+template class small_vector<int, 10>;
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::small_vector
+ < test::movable_and_copyable_int
+ , 10
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::small_vector
+ < test::movable_and_copyable_int
+ , 10
+ , allocator<test::movable_and_copyable_int> >;
+
+}}
+
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp
new file mode 100644
index 000000000..b11b4c65c
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/stable_vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::stable_vector<empty>;
+volatile ::boost::container::stable_vector<empty> dummy;
+
+#include <boost/container/node_allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class stable_vector<test::movable_and_copyable_int,
+ test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class stable_vector
+ < test::movable_and_copyable_int
+ , node_allocator<test::movable_and_copyable_int> >;
+
+template class stable_vector_iterator<int*, false>;
+template class stable_vector_iterator<int*, true >;
+
+}}
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp
new file mode 100644
index 000000000..081775df8
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp
@@ -0,0 +1,33 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/static_vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::static_vector<empty, 2>;
+volatile ::boost::container::static_vector<empty, 2> dummy;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::static_vector<int, 10>;
+
+}}
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_string_test.cpp b/src/boost/libs/container/test/explicit_inst_string_test.cpp
new file mode 100644
index 000000000..fd7696921
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_string_test.cpp
@@ -0,0 +1,44 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/string.hpp>
+
+template class ::boost::container::basic_string<char>;
+volatile ::boost::container::basic_string<char> dummy;
+
+#include <boost/container/vector.hpp>
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+typedef test::simple_allocator<char> SimpleCharAllocator;
+typedef basic_string<char, std::char_traits<char>, SimpleCharAllocator> SimpleString;
+typedef test::simple_allocator<SimpleString> SimpleStringAllocator;
+typedef test::simple_allocator<wchar_t> SimpleWCharAllocator;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, SimpleWCharAllocator> SimpleWString;
+typedef test::simple_allocator<SimpleWString> SimpleWStringAllocator;
+
+//Explicit instantiations of container::basic_string
+template class basic_string<char, std::char_traits<char>, SimpleCharAllocator>;
+template class basic_string<wchar_t, std::char_traits<wchar_t>, SimpleWCharAllocator>;
+template class basic_string<char, std::char_traits<char>, std::allocator<char> >;
+template class basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >;
+
+//Explicit instantiation of container::vectors of container::strings
+template class vector<SimpleString, SimpleStringAllocator>;
+template class vector<SimpleWString, SimpleWStringAllocator>;
+
+}}
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/explicit_inst_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_vector_test.cpp
new file mode 100644
index 000000000..619dfc956
--- /dev/null
+++ b/src/boost/libs/container/test/explicit_inst_vector_test.cpp
@@ -0,0 +1,47 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::vector<empty>;
+volatile ::boost::container::vector<empty> dummy;
+
+#include <boost/container/allocator.hpp>
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::vector
+ < test::movable_and_copyable_int
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::vector
+ < test::movable_and_copyable_int
+ , allocator<test::movable_and_copyable_int> >;
+
+template class vec_iterator<int*, true >;
+template class vec_iterator<int*, false>;
+
+} //namespace boost {
+} //namespace container {
+
+int main()
+{
+ return 0;
+}
diff --git a/src/boost/libs/container/test/flat_map_adaptor_test.cpp b/src/boost/libs/container/test/flat_map_adaptor_test.cpp
new file mode 100644
index 000000000..520ef3c14
--- /dev/null
+++ b/src/boost/libs/container/test/flat_map_adaptor_test.cpp
@@ -0,0 +1,104 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2019. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/flat_map.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "map_test.hpp"
+#include <map>
+
+using namespace boost::container;
+
+template<class VoidAllocatorOrContainer>
+struct GetMapContainer
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef std::pair<ValueType, ValueType> type_t;
+ typedef flat_map< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+ > map_type;
+
+ typedef flat_multimap< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+ > multimap_type;
+ };
+};
+
+int main()
+{
+ using namespace boost::container::test;
+
+ ////////////////////////////////////
+ // Testing sequence container implementations
+ ////////////////////////////////////
+ {
+ typedef std::map<int, int> MyStdMap;
+ typedef std::multimap<int, int> MyStdMultiMap;
+
+ if (0 != test::map_test
+ < GetMapContainer<vector<std::pair<int, int> > >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<vector<std::pair<int, int> > >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<vector<std::pair<int, int> > >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<small_vector<std::pair<int, int>, 7> >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<small_vector<std::pair<int, int>, 7> >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<small_vector<std::pair<int, int>, 7> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<static_vector<std::pair<int, int>, MaxElem * 10> >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<static_vector<std::pair<int, int>, MaxElem * 10> >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<static_vector<std::pair<int, int>, MaxElem * 10> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<stable_vector<std::pair<int, int> > >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<stable_vector<std::pair<int, int> > >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<stable_vector<std::pair<int, int> > >" << std::endl;
+ return 1;
+ }
+
+
+ if (0 != test::map_test
+ < GetMapContainer<deque<std::pair<int, int> > >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<deque<std::pair<int, int> > >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<deque<std::pair<int, int> > >" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/flat_map_test.cpp b/src/boost/libs/container/test/flat_map_test.cpp
new file mode 100644
index 000000000..f5caff7ac
--- /dev/null
+++ b/src/boost/libs/container/test/flat_map_test.cpp
@@ -0,0 +1,838 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+
+#include <vector>
+
+#include <boost/container/flat_map.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "print_container.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "container_common_tests.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <map>
+#include <utility>
+
+
+using namespace boost::container;
+
+class recursive_flat_map
+{
+ public:
+ recursive_flat_map(const recursive_flat_map &c)
+ : id_(c.id_), map_(c.map_)
+ {}
+
+ recursive_flat_map & operator =(const recursive_flat_map &c)
+ {
+ id_ = c.id_;
+ map_= c.map_;
+ return *this;
+ }
+
+ int id_;
+ flat_map<recursive_flat_map, recursive_flat_map> map_;
+ flat_map<recursive_flat_map, recursive_flat_map>::iterator it_;
+ flat_map<recursive_flat_map, recursive_flat_map>::const_iterator cit_;
+ flat_map<recursive_flat_map, recursive_flat_map>::reverse_iterator rit_;
+ flat_map<recursive_flat_map, recursive_flat_map>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_flat_map &a, const recursive_flat_map &b)
+ { return a.id_ < b.id_; }
+};
+
+
+class recursive_flat_multimap
+{
+public:
+ recursive_flat_multimap(const recursive_flat_multimap &c)
+ : id_(c.id_), map_(c.map_)
+ {}
+
+ recursive_flat_multimap & operator =(const recursive_flat_multimap &c)
+ {
+ id_ = c.id_;
+ map_= c.map_;
+ return *this;
+ }
+ int id_;
+ flat_multimap<recursive_flat_multimap, recursive_flat_multimap> map_;
+ flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::iterator it_;
+ flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_iterator cit_;
+ flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::reverse_iterator rit_;
+ flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_flat_multimap &a, const recursive_flat_multimap &b)
+ { return a.id_ < b.id_; }
+};
+
+template<class C>
+void test_move()
+{
+ //Now test move semantics
+ C original;
+ C move_ctor(boost::move(original));
+ C move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+}
+
+
+namespace boost{
+namespace container {
+namespace test{
+
+bool flat_tree_ordered_insertion_test()
+{
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+
+ //Ordered insertion multimap
+ {
+ std::multimap<int, int> int_mmap;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ //Construction insertion
+ flat_multimap<int, int> fmmap(ordered_range, int_mmap.begin(), int_mmap.end());
+ if(!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ //Insertion when empty
+ fmmap.clear();
+ fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
+ if(!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ //Re-insertion
+ fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
+ std::multimap<int, int> int_mmap2(int_mmap);
+ int_mmap2.insert(int_mmap.begin(), int_mmap.end());
+ if(!CheckEqualContainers(int_mmap2, fmmap))
+ return false;
+ //Re-re-insertion
+ fmmap.insert(ordered_range, int_mmap2.begin(), int_mmap2.end());
+ std::multimap<int, int> int_mmap4(int_mmap2);
+ int_mmap4.insert(int_mmap2.begin(), int_mmap2.end());
+ if(!CheckEqualContainers(int_mmap4, fmmap))
+ return false;
+ //Re-re-insertion of even
+ std::multimap<int, int> int_even_mmap;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ fmmap.insert(ordered_range, int_even_mmap.begin(), int_even_mmap.end());
+ int_mmap4.insert(int_even_mmap.begin(), int_even_mmap.end());
+ if(!CheckEqualContainers(int_mmap4, fmmap))
+ return false;
+ }
+
+ //Ordered insertion map
+ {
+ std::map<int, int> int_map;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ //Construction insertion
+ flat_map<int, int> fmap(ordered_unique_range, int_map.begin(), int_map.end());
+ if(!CheckEqualContainers(int_map, fmap))
+ return false;
+ //Insertion when empty
+ fmap.clear();
+ fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
+ if(!CheckEqualContainers(int_map, fmap))
+ return false;
+ //Re-insertion
+ fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
+ std::map<int, int> int_map2(int_map);
+ int_map2.insert(int_map.begin(), int_map.end());
+ if(!CheckEqualContainers(int_map2, fmap))
+ return false;
+ //Re-re-insertion
+ fmap.insert(ordered_unique_range, int_map2.begin(), int_map2.end());
+ std::map<int, int> int_map4(int_map2);
+ int_map4.insert(int_map2.begin(), int_map2.end());
+ if(!CheckEqualContainers(int_map4, fmap))
+ return false;
+ //Re-re-insertion of even
+ std::map<int, int> int_even_map;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ fmap.insert(ordered_unique_range, int_even_map.begin(), int_even_map.end());
+ int_map4.insert(int_even_map.begin(), int_even_map.end());
+ if(!CheckEqualContainers(int_map4, fmap))
+ return false;
+ }
+
+ return true;
+}
+
+bool constructor_template_auto_deduction_test()
+{
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+ {
+ std::map<int, int> int_map;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ std::multimap<int, int> int_mmap;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+
+ typedef std::less<int> comp_int_t;
+ typedef std::allocator<std::pair<int, int> > alloc_pair_int_t;
+
+ //range
+ {
+ auto fmap = flat_map(int_map.begin(), int_map.end());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp
+ {
+ auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fmap = flat_map(int_map.begin(), int_map.end(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+
+ //ordered_unique_range / ordered_range
+
+ //range
+ {
+ auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end());
+ if(!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end());
+ if(!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp
+ {
+ auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
+
+template< class RandomIt >
+void random_shuffle( RandomIt first, RandomIt last )
+{
+ typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
+ difference_type n = last - first;
+ for (difference_type i = n-1; i > 0; --i) {
+ difference_type j = std::rand() % (i+1);
+ if(j != i) {
+ boost::adl_move_swap(first[i], first[j]);
+ }
+ }
+}
+
+bool flat_tree_extract_adopt_test()
+{
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+
+ //extract/adopt map
+ {
+ //Construction insertion
+ flat_map<int, int> fmap;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ }
+
+ flat_map<int, int> fmap_copy(fmap);
+ flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
+ if(!fmap.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmap_copy))
+ return false;
+
+ seq.insert(seq.end(), fmap_copy.begin(), fmap_copy.end());
+ boost::container::test::random_shuffle(seq.begin(), seq.end());
+ fmap.adopt_sequence(boost::move(seq));
+ if(!CheckEqualContainers(fmap, fmap_copy))
+ return false;
+ }
+
+ //extract/adopt map, ordered_unique_range
+ {
+ //Construction insertion
+ flat_map<int, int> fmap;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ }
+
+ flat_map<int, int> fmap_copy(fmap);
+ flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
+ if(!fmap.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmap_copy))
+ return false;
+
+ fmap.adopt_sequence(ordered_unique_range, boost::move(seq));
+ if(!CheckEqualContainers(fmap, fmap_copy))
+ return false;
+ }
+
+ //extract/adopt multimap
+ {
+ //Construction insertion
+ flat_multimap<int, int> fmmap;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ }
+
+ flat_multimap<int, int> fmmap_copy(fmmap);
+ flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
+ if(!fmmap.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmmap_copy))
+ return false;
+
+ boost::container::test::random_shuffle(seq.begin(), seq.end());
+ fmmap.adopt_sequence(boost::move(seq));
+ if(!CheckEqualContainers(fmmap, fmmap_copy))
+ return false;
+ }
+
+ //extract/adopt multimap, ordered_range
+ {
+ //Construction insertion
+ flat_multimap<int, int> fmmap;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+ }
+
+ flat_multimap<int, int> fmmap_copy(fmmap);
+ flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
+ if(!fmmap.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmmap_copy))
+ return false;
+
+ fmmap.adopt_sequence(ordered_range, boost::move(seq));
+ if(!CheckEqualContainers(fmmap, fmmap_copy))
+ return false;
+ }
+
+ return true;
+}
+
+}}}
+
+template<class VoidAllocatorOrContainer>
+struct GetMapContainer
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef std::pair<ValueType, ValueType> type_t;
+ typedef flat_map< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+ > map_type;
+
+ typedef flat_multimap< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+ > multimap_type;
+ };
+};
+
+struct boost_container_flat_map;
+struct boost_container_flat_multimap;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_flat_map>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef typename boost::container::allocator_traits<Allocator>::
+ template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
+ typedef boost::container::flat_map<T, T, std::less<T>, TypeAllocator> type;
+ };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_flat_multimap>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef typename boost::container::allocator_traits<Allocator>::
+ template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
+ typedef boost::container::flat_multimap<T, T, std::less<T>, TypeAllocator> type;
+ };
+};
+
+template <class Key, class T, class Compare, class Allocator>
+struct get_real_stored_allocator<flat_map<Key, T, Compare, Allocator> >
+{
+ typedef typename flat_map<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
+};
+
+template <class Key, class T, class Compare, class Allocator>
+struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
+{
+ typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
+};
+
+bool test_heterogeneous_lookups()
+{
+ BOOST_STATIC_ASSERT((dtl::is_transparent<less_transparent>::value));
+ BOOST_STATIC_ASSERT(!(dtl::is_transparent<std::less<int> >::value));
+ typedef flat_map<int, char, less_transparent> map_t;
+ typedef flat_multimap<int, char, less_transparent> mmap_t;
+ typedef map_t::value_type value_type;
+
+ map_t map1;
+ mmap_t mmap1;
+
+ const map_t &cmap1 = map1;
+ const mmap_t &cmmap1 = mmap1;
+
+ if(!map1.insert_or_assign(1, 'a').second)
+ return false;
+ if( map1.insert_or_assign(1, 'b').second)
+ return false;
+ if(!map1.insert_or_assign(2, 'c').second)
+ return false;
+ if( map1.insert_or_assign(2, 'd').second)
+ return false;
+ if(!map1.insert_or_assign(3, 'e').second)
+ return false;
+
+ if(map1.insert_or_assign(1, 'a').second)
+ return false;
+ if(map1.insert_or_assign(1, 'b').second)
+ return false;
+ if(map1.insert_or_assign(2, 'c').second)
+ return false;
+ if(map1.insert_or_assign(2, 'd').second)
+ return false;
+ if(map1.insert_or_assign(3, 'e').second)
+ return false;
+
+ mmap1.insert(value_type(1, 'a'));
+ mmap1.insert(value_type(1, 'b'));
+ mmap1.insert(value_type(2, 'c'));
+ mmap1.insert(value_type(2, 'd'));
+ mmap1.insert(value_type(3, 'e'));
+
+ const test::non_copymovable_int find_me(2);
+
+ //find
+ if(map1.find(find_me)->second != 'd')
+ return false;
+ if(cmap1.find(find_me)->second != 'd')
+ return false;
+ if(mmap1.find(find_me)->second != 'c')
+ return false;
+ if(cmmap1.find(find_me)->second != 'c')
+ return false;
+
+ //count
+ if(map1.count(find_me) != 1)
+ return false;
+ if(cmap1.count(find_me) != 1)
+ return false;
+ if(mmap1.count(find_me) != 2)
+ return false;
+ if(cmmap1.count(find_me) != 2)
+ return false;
+
+ //contains
+ if(!map1.contains(find_me))
+ return false;
+ if(!cmap1.contains(find_me))
+ return false;
+ if(!mmap1.contains(find_me))
+ return false;
+ if(!cmmap1.contains(find_me))
+ return false;
+
+ //lower_bound
+ if(map1.lower_bound(find_me)->second != 'd')
+ return false;
+ if(cmap1.lower_bound(find_me)->second != 'd')
+ return false;
+ if(mmap1.lower_bound(find_me)->second != 'c')
+ return false;
+ if(cmmap1.lower_bound(find_me)->second != 'c')
+ return false;
+
+ //upper_bound
+ if(map1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(cmap1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(mmap1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(cmmap1.upper_bound(find_me)->second != 'e')
+ return false;
+
+ //equal_range
+ if(map1.equal_range(find_me).first->second != 'd')
+ return false;
+ if(cmap1.equal_range(find_me).second->second != 'e')
+ return false;
+ if(mmap1.equal_range(find_me).first->second != 'c')
+ return false;
+ if(cmmap1.equal_range(find_me).second->second != 'e')
+ return false;
+
+ return true;
+}
+
+// An ordered sequence of std:pair is also ordered by std::pair::first.
+struct with_lookup_by_first
+{
+ typedef void is_transparent;
+ inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const
+ {
+ return a < b;
+ }
+ inline bool operator()(std::pair<int, int> a, int first) const
+ {
+ return a.first < first;
+ }
+ inline bool operator()(int first, std::pair<int, int> b) const
+ {
+ return first < b.first;
+ }
+};
+
+bool test_heterogeneous_lookup_by_partial_key()
+{
+ typedef flat_map<std::pair<int, int>,int, with_lookup_by_first> map_t;
+
+ map_t map1;
+ map1[std::pair<int, int>(0, 1)] = 3;
+ map1[std::pair<int, int>(0, 2)] = 3;
+
+ std::pair<map_t::iterator, map_t::iterator> const first_0_range = map1.equal_range(0);
+
+ if(2 != (first_0_range.second - first_0_range.first))
+ return false;
+
+ if(2 != map1.count(0))
+ return false;
+ return true;
+}
+
+}}} //namespace boost::container::test
+
+int main()
+{
+ using namespace boost::container::test;
+
+ //Allocator argument container
+ {
+ flat_map<int, int> map_((flat_map<int, int>::allocator_type()));
+ flat_multimap<int, int> multimap_((flat_multimap<int, int>::allocator_type()));
+ }
+ //Now test move semantics
+ {
+ test_move<flat_map<recursive_flat_map, recursive_flat_map> >();
+ test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >();
+ }
+ //Now test nth/index_of
+ {
+ flat_map<int, int> map;
+ flat_multimap<int, int> mmap;
+
+ map.insert(std::pair<int, int>(0, 0));
+ map.insert(std::pair<int, int>(1, 0));
+ map.insert(std::pair<int, int>(2, 0));
+ mmap.insert(std::pair<int, int>(0, 0));
+ mmap.insert(std::pair<int, int>(1, 0));
+ mmap.insert(std::pair<int, int>(2, 0));
+ if(!boost::container::test::test_nth_index_of(map))
+ return 1;
+ if(!boost::container::test::test_nth_index_of(mmap))
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Ordered insertion test
+ ////////////////////////////////////
+ if(!flat_tree_ordered_insertion_test()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction test
+ ////////////////////////////////////
+ if(!constructor_template_auto_deduction_test()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Extract/Adopt test
+ ////////////////////////////////////
+ if(!flat_tree_extract_adopt_test()){
+ return 1;
+ }
+
+ if (!boost::container::test::instantiate_constructors<flat_map<int, int>, flat_multimap<int, int> >())
+ return 1;
+
+ if (!test_heterogeneous_lookups())
+ return 1;
+
+ if (!test_heterogeneous_lookup_by_partial_key())
+ return 1;
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ {
+ typedef std::map<int, int> MyStdMap;
+ typedef std::multimap<int, int> MyStdMultiMap;
+
+ if (0 != test::map_test
+ < GetMapContainer<std::allocator<void> >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<std::allocator<void> >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<std::allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<new_allocator<void> >::apply<int>::map_type
+ , MyStdMap
+ , GetMapContainer<new_allocator<void> >::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<new_allocator<void> >::apply<test::movable_int>::map_type
+ , MyStdMap
+ , GetMapContainer<new_allocator<void> >::apply<test::movable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::map_type
+ , MyStdMap
+ , GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::map_type
+ , MyStdMap
+ , GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+ }
+
+ if(!boost::container::test::test_map_support_for_initialization_list_for<flat_map<int, int> >())
+ return 1;
+
+ if (!boost::container::test::test_map_support_for_initialization_list_for<flat_multimap<int, int> >())
+ return 1;
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
+
+ if(!boost::container::test::test_emplace<flat_map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+ return 1;
+ if(!boost::container::test::test_emplace<flat_multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_flat_map>())
+ return 1;
+
+ if(!boost::container::test::test_propagate_allocator<boost_container_flat_multimap>())
+ return 1;
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::flat_map<int, int> cont_int;
+ cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+ {
+ typedef boost::container::flat_multimap<int, int> cont_int;
+ cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::dtl::pair<int, int> value_t;
+ typedef boost::container::dtl::select1st<int> key_of_value_t;
+ // flat_map, default
+ {
+ typedef boost::container::new_allocator<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_map<int, int> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_map, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_map, vector
+ {
+ typedef boost::container::vector<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_map, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_map, std::vector
+ {
+ typedef std::vector<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_map, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multimap, default
+ {
+ typedef boost::container::new_allocator<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_multimap<int, int> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multimap, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multimap, vector
+ {
+ typedef boost::container::vector<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multimap, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multimap, std::vector
+ {
+ typedef std::vector<value_t> alloc_or_cont_t;
+ typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multimap, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/flat_set_adaptor_test.cpp b/src/boost/libs/container/test/flat_set_adaptor_test.cpp
new file mode 100644
index 000000000..b59ab1794
--- /dev/null
+++ b/src/boost/libs/container/test/flat_set_adaptor_test.cpp
@@ -0,0 +1,101 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2019. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/flat_set.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "set_test.hpp"
+#include <set>
+
+using namespace boost::container;
+
+template<class VoidAllocatorOrContainer>
+struct GetSetContainer
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef flat_set < ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+ > set_type;
+
+ typedef flat_multiset < ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+ > multiset_type;
+ };
+};
+
+int main()
+{
+ using namespace boost::container::test;
+
+ ////////////////////////////////////
+ // Testing sequence container implementations
+ ////////////////////////////////////
+ {
+ typedef std::set<int> MyStdSet;
+ typedef std::multiset<int> MyStdMultiSet;
+
+ if (0 != test::set_test
+ < GetSetContainer<vector<int> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<vector<int> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<vector<int> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<small_vector<int, 7> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<small_vector<int, 7> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<small_vector<int, 7> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<static_vector<int, MaxElem * 10> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<static_vector<int, MaxElem * 10> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<static_vector<int, MaxElem * 10> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<stable_vector<int> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<stable_vector<int> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<stable_vector<int> >" << std::endl;
+ return 1;
+ }
+
+
+ if (0 != test::set_test
+ < GetSetContainer<deque<int> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<deque<int> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<deque<int> >" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/flat_set_test.cpp b/src/boost/libs/container/test/flat_set_test.cpp
new file mode 100644
index 000000000..7927b99a4
--- /dev/null
+++ b/src/boost/libs/container/test/flat_set_test.cpp
@@ -0,0 +1,933 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <iostream>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include <boost/container/flat_set.hpp>
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "print_container.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "set_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "container_common_tests.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+//Test recursive structures
+class recursive_flat_set
+{
+ public:
+ recursive_flat_set(const recursive_flat_set &c)
+ : id_(c.id_), flat_set_(c.flat_set_)
+ {}
+
+ recursive_flat_set & operator =(const recursive_flat_set &c)
+ {
+ id_ = c.id_;
+ flat_set_= c.flat_set_;
+ return *this;
+ }
+ int id_;
+ flat_set<recursive_flat_set> flat_set_;
+ flat_set<recursive_flat_set>::iterator it_;
+ flat_set<recursive_flat_set>::const_iterator cit_;
+ flat_set<recursive_flat_set>::reverse_iterator rit_;
+ flat_set<recursive_flat_set>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_flat_set &a, const recursive_flat_set &b)
+ { return a.id_ < b.id_; }
+};
+
+
+//Test recursive structures
+class recursive_flat_multiset
+{
+ public:
+ recursive_flat_multiset(const recursive_flat_multiset &c)
+ : id_(c.id_), flat_multiset_(c.flat_multiset_)
+ {}
+
+ recursive_flat_multiset & operator =(const recursive_flat_multiset &c)
+ {
+ id_ = c.id_;
+ flat_multiset_= c.flat_multiset_;
+ return *this;
+ }
+ int id_;
+ flat_multiset<recursive_flat_multiset> flat_multiset_;
+ flat_multiset<recursive_flat_multiset>::iterator it_;
+ flat_multiset<recursive_flat_multiset>::const_iterator cit_;
+ flat_multiset<recursive_flat_multiset>::reverse_iterator rit_;
+ flat_multiset<recursive_flat_multiset>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b)
+ { return a.id_ < b.id_; }
+};
+
+
+template<class C>
+void test_move()
+{
+ //Now test move semantics
+ C original;
+ C move_ctor(boost::move(original));
+ C move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+}
+
+namespace boost{
+namespace container {
+namespace test{
+
+bool flat_tree_ordered_insertion_test()
+{
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+
+ //Ordered insertion multiset
+ {
+ std::multiset<int> int_mset;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_mset.insert(static_cast<int>(i));
+ }
+ //Construction insertion
+ flat_multiset<int> fmset(ordered_range, int_mset.begin(), int_mset.end());
+ if(!CheckEqualContainers(int_mset, fmset))
+ return false;
+ //Insertion when empty
+ fmset.clear();
+ fmset.insert(ordered_range, int_mset.begin(), int_mset.end());
+ if(!CheckEqualContainers(int_mset, fmset))
+ return false;
+ //Re-insertion
+ fmset.insert(ordered_range, int_mset.begin(), int_mset.end());
+ std::multiset<int> int_mset2(int_mset);
+ int_mset2.insert(int_mset.begin(), int_mset.end());
+ if(!CheckEqualContainers(int_mset2, fmset))
+ return false;
+ //Re-re-insertion
+ fmset.insert(ordered_range, int_mset2.begin(), int_mset2.end());
+ std::multiset<int> int_mset4(int_mset2);
+ int_mset4.insert(int_mset2.begin(), int_mset2.end());
+ if(!CheckEqualContainers(int_mset4, fmset))
+ return false;
+ //Re-re-insertion of even
+ std::multiset<int> int_even_mset;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_mset.insert(static_cast<int>(i));
+ }
+ fmset.insert(ordered_range, int_even_mset.begin(), int_even_mset.end());
+ int_mset4.insert(int_even_mset.begin(), int_even_mset.end());
+ if(!CheckEqualContainers(int_mset4, fmset))
+ return false;
+
+ //Re-re-insertion using in-place merge
+ fmset.reserve(fmset.size() + int_mset2.size());
+ fmset.insert(ordered_range, int_mset2.begin(), int_mset2.end());
+ std::multiset<int> int_mset5(int_mset2);
+ int_mset4.insert(int_mset5.begin(), int_mset5.end());
+ if(!CheckEqualContainers(int_mset4, fmset))
+ return false;
+ //Re-re-insertion of even
+ std::multiset<int> int_even_mset2;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_even_mset2.insert(static_cast<int>(i));
+ }
+ fmset.reserve(fmset.size() + int_even_mset2.size());
+ fmset.insert(ordered_range, int_even_mset2.begin(), int_even_mset2.end());
+ int_mset4.insert(int_even_mset2.begin(), int_even_mset2.end());
+ if(!CheckEqualContainers(int_mset4, fmset))
+ return false;
+ }
+
+ //Ordered insertion set
+ {
+ std::set<int> int_set;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_set.insert(static_cast<int>(i));
+ }
+ //Construction insertion
+ flat_set<int> fset(ordered_unique_range, int_set.begin(), int_set.end());
+ if(!CheckEqualContainers(int_set, fset))
+ return false;
+ //Insertion when empty
+ fset.clear();
+ fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+ if(!CheckEqualContainers(int_set, fset))
+ return false;
+ //Re-insertion
+ fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+ std::set<int> int_set2(int_set);
+ int_set2.insert(int_set.begin(), int_set.end());
+ if(!CheckEqualContainers(int_set2, fset))
+ return false;
+ //Re-re-insertion
+ fset.insert(ordered_unique_range, int_set2.begin(), int_set2.end());
+ std::set<int> int_set4(int_set2);
+ int_set4.insert(int_set2.begin(), int_set2.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ //Re-re-insertion of even
+ std::set<int> int_even_set;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ //Partial Re-re-insertion of even
+ int_even_set.clear();
+ for(std::size_t i = 0; i < NumElements; i+=4){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ fset.clear();
+ int_set4.clear();
+ //insert 0,4,8,12...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ for(std::size_t i = 2; i < NumElements; i+=4){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ //insert 0,2,4,6,8,10,12...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ int_even_set.clear();
+ for(std::size_t i = 0; i < NumElements; i+=8){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ fset.clear();
+ int_set4.clear();
+ //insert 0,8,16...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ //insert 0,2,4,6,8,10,12...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+
+
+ int_even_set.clear();
+ for(std::size_t i = 0; i < NumElements; i+=8){
+ int_even_set.insert(static_cast<int>(i));
+ int_even_set.insert(static_cast<int>(i+2));
+ }
+ int_even_set.insert(static_cast<int>(NumElements-2));
+ fset.clear();
+ int_set4.clear();
+ //insert 0,2,8,10...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ for(std::size_t i = 0; i < NumElements; i+=2){
+ int_even_set.insert(static_cast<int>(i));
+ }
+ //insert 0,2,4,6,8,10,12...
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+
+ //add even/odd values with not enough capacity
+ flat_set<int>().swap(fset);
+ int_set4.clear();
+ int_set.clear();
+
+ fset.reserve(int_even_set.size());
+ fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+ int_set4.insert(int_even_set.begin(), int_even_set.end());
+
+ for(std::size_t i = 0; i < NumElements*2; i+=2){
+ int_set.insert(static_cast<int>(i));
+ int_set.insert(static_cast<int>(i+1));
+ }
+
+ fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+ int_set4.insert(int_set.begin(), int_set.end());
+ if(!CheckEqualContainers(int_set4, fset))
+ return false;
+ }
+
+ return true;
+}
+
+bool constructor_template_auto_deduction_test()
+{
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+ {
+ std::set<int> int_set;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_set.insert(static_cast<int>(i));
+ }
+ std::multiset<int> int_mset;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_mset.insert(static_cast<int>(i));
+ }
+
+ typedef std::less<int> comp_int_t;
+ typedef std::allocator<int> alloc_int_t;
+
+ //range
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = flat_set(int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+
+ //ordered_unique_range / ordered_range
+
+ //range
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
+
+template< class RandomIt >
+void random_shuffle( RandomIt first, RandomIt last )
+{
+ typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
+ difference_type n = last - first;
+ for (difference_type i = n-1; i > 0; --i) {
+ difference_type j = std::rand() % (i+1);
+ if(j != i) {
+ boost::adl_move_swap(first[i], first[j]);
+ }
+ }
+}
+
+bool flat_tree_extract_adopt_test()
+{
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+
+ //extract/adopt set
+ {
+ //Construction insertion
+ flat_set<int> fset;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fset.insert(static_cast<int>(i));
+ }
+
+ flat_set<int> fset_copy(fset);
+ flat_set<int>::sequence_type seq(fset.extract_sequence());
+ if(!fset.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fset_copy))
+ return false;
+
+ seq.insert(seq.end(), fset_copy.begin(), fset_copy.end());
+ boost::container::test::random_shuffle(seq.begin(), seq.end());
+ fset.adopt_sequence(boost::move(seq));
+ if(!CheckEqualContainers(fset, fset_copy))
+ return false;
+ }
+
+ //extract/adopt set, ordered_unique_range
+ {
+ //Construction insertion
+ flat_set<int> fset;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fset.insert(static_cast<int>(i));
+ }
+
+ flat_set<int> fset_copy(fset);
+ flat_set<int>::sequence_type seq(fset.extract_sequence());
+ if(!fset.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fset_copy))
+ return false;
+
+ fset.adopt_sequence(ordered_unique_range, boost::move(seq));
+ if(!CheckEqualContainers(fset, fset_copy))
+ return false;
+ }
+
+ //extract/adopt multiset
+ {
+ //Construction insertion
+ flat_multiset<int> fmset;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmset.insert(static_cast<int>(i));
+ fmset.insert(static_cast<int>(i));
+ }
+
+ flat_multiset<int> fmset_copy(fmset);
+ flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
+ if(!fmset.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmset_copy))
+ return false;
+
+ boost::container::test::random_shuffle(seq.begin(), seq.end());
+ fmset.adopt_sequence(boost::move(seq));
+ if(!CheckEqualContainers(fmset, fmset_copy))
+ return false;
+ }
+
+ //extract/adopt multiset, ordered_range
+ {
+ //Construction insertion
+ flat_multiset<int> fmset;
+
+ for(std::size_t i = 0; i != NumElements; ++i){
+ fmset.insert(static_cast<int>(i));
+ fmset.insert(static_cast<int>(i));
+ }
+
+ flat_multiset<int> fmset_copy(fmset);
+ flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
+ if(!fmset.empty())
+ return false;
+ if(!CheckEqualContainers(seq, fmset_copy))
+ return false;
+
+ fmset.adopt_sequence(ordered_range, boost::move(seq));
+ if(!CheckEqualContainers(fmset, fmset_copy))
+ return false;
+ }
+
+ return true;
+}
+
+bool test_heterogeneous_lookups()
+{
+ typedef flat_set<int, test::less_transparent> set_t;
+ typedef flat_multiset<int, test::less_transparent> mset_t;
+
+ set_t set1;
+ mset_t mset1;
+
+ const set_t &cset1 = set1;
+ const mset_t &cmset1 = mset1;
+
+ set1.insert(1);
+ set1.insert(1);
+ set1.insert(2);
+ set1.insert(2);
+ set1.insert(3);
+
+ mset1.insert(1);
+ mset1.insert(1);
+ mset1.insert(2);
+ mset1.insert(2);
+ mset1.insert(3);
+
+ const test::non_copymovable_int find_me(2);
+
+ //find
+ if(*set1.find(find_me) != 2)
+ return false;
+ if(*cset1.find(find_me) != 2)
+ return false;
+ if(*mset1.find(find_me) != 2)
+ return false;
+ if(*cmset1.find(find_me) != 2)
+ return false;
+
+ //count
+ if(set1.count(find_me) != 1)
+ return false;
+ if(cset1.count(find_me) != 1)
+ return false;
+ if(mset1.count(find_me) != 2)
+ return false;
+ if(cmset1.count(find_me) != 2)
+ return false;
+
+ //contains
+ if(!set1.contains(find_me))
+ return false;
+ if(!cset1.contains(find_me))
+ return false;
+ if(!mset1.contains(find_me))
+ return false;
+ if(!cmset1.contains(find_me))
+ return false;
+
+ //lower_bound
+ if(*set1.lower_bound(find_me) != 2)
+ return false;
+ if(*cset1.lower_bound(find_me) != 2)
+ return false;
+ if(*mset1.lower_bound(find_me) != 2)
+ return false;
+ if(*cmset1.lower_bound(find_me) != 2)
+ return false;
+
+ //upper_bound
+ if(*set1.upper_bound(find_me) != 3)
+ return false;
+ if(*cset1.upper_bound(find_me) != 3)
+ return false;
+ if(*mset1.upper_bound(find_me) != 3)
+ return false;
+ if(*cmset1.upper_bound(find_me) != 3)
+ return false;
+
+ //equal_range
+ if(*set1.equal_range(find_me).first != 2)
+ return false;
+ if(*cset1.equal_range(find_me).second != 3)
+ return false;
+ if(*mset1.equal_range(find_me).first != 2)
+ return false;
+ if(*cmset1.equal_range(find_me).second != 3)
+ return false;
+
+ return true;
+}
+
+// An ordered sequence of std:pair is also ordered by std::pair::first.
+struct with_lookup_by_first
+{
+ typedef void is_transparent;
+ inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const
+ {
+ return a < b;
+ }
+ inline bool operator()(std::pair<int, int> a, int first) const
+ {
+ return a.first < first;
+ }
+ inline bool operator()(int first, std::pair<int, int> b) const
+ {
+ return first < b.first;
+ }
+};
+
+bool test_heterogeneous_lookup_by_partial_key()
+{
+ typedef flat_set<std::pair<int, int>, with_lookup_by_first> set_t;
+
+ set_t set1;
+ set1.insert(std::pair<int, int>(0, 1));
+ set1.insert(std::pair<int, int>(0, 2));
+
+ std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(0);
+ if(2 != (first_0_range.second - first_0_range.first))
+ return false;
+
+ if(2 != set1.count(0))
+ return false;
+ return true;
+}
+
+}}}
+
+template<class VoidAllocatorOrContainer>
+struct GetSetContainer
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef flat_set < ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+ > set_type;
+
+ typedef flat_multiset < ValueType
+ , std::less<ValueType>
+ , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+ > multiset_type;
+ };
+};
+
+template<typename FlatSetType>
+bool test_support_for_initialization_list_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ const std::initializer_list<int> il
+ = {1, 2};
+
+ const FlatSetType expected(il.begin(), il.end());
+ {
+ const FlatSetType sil = il;
+ if (sil != expected)
+ return false;
+
+ const FlatSetType sil_ordered(ordered_unique_range, il);
+ if(sil_ordered != expected)
+ return false;
+
+ FlatSetType sil_assign = {99};
+ sil_assign = il;
+ if(sil_assign != expected)
+ return false;
+ }
+ {
+ FlatSetType sil;
+ sil.insert(il);
+ if(sil != expected)
+ return false;
+ }
+ return true;
+#endif
+ return true;
+}
+
+struct boost_container_flat_set;
+struct boost_container_flat_multiset;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_flat_set>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::flat_set<T, std::less<T>, Allocator> type;
+ };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_flat_multiset>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::flat_multiset<T, std::less<T>, Allocator> type;
+ };
+};
+
+}}} //boost::container::test
+
+int main()
+{
+ using namespace boost::container::test;
+
+ //Allocator argument container
+ {
+ flat_set<int> set_((flat_set<int>::allocator_type()));
+ flat_multiset<int> multiset_((flat_multiset<int>::allocator_type()));
+ }
+ //Now test move semantics
+ {
+ test_move<flat_set<recursive_flat_set> >();
+ test_move<flat_multiset<recursive_flat_multiset> >();
+ }
+ //Now test nth/index_of
+ {
+ flat_set<int> set;
+ flat_multiset<int> mset;
+
+ set.insert(0);
+ set.insert(1);
+ set.insert(2);
+ mset.insert(0);
+ mset.insert(1);
+ mset.insert(2);
+ if(!boost::container::test::test_nth_index_of(set))
+ return 1;
+ if(!boost::container::test::test_nth_index_of(mset))
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Ordered insertion test
+ ////////////////////////////////////
+ if(!flat_tree_ordered_insertion_test()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction test
+ ////////////////////////////////////
+ if (!constructor_template_auto_deduction_test()) {
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Extract/Adopt test
+ ////////////////////////////////////
+ if(!flat_tree_extract_adopt_test()){
+ return 1;
+ }
+
+ if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >())
+ return 1;
+
+ if(!test_heterogeneous_lookups()){
+ return 1;
+ }
+
+ if(!test_heterogeneous_lookup_by_partial_key()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ {
+ typedef std::set<int> MyStdSet;
+ typedef std::multiset<int> MyStdMultiSet;
+
+ if (0 != test::set_test
+ < GetSetContainer<std::allocator<void> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<std::allocator<void> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<std::allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::movable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::movable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::set_type
+ , MyStdSet
+ , GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void> >" << std::endl;
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
+
+ if(!boost::container::test::test_emplace<flat_set<test::EmplaceInt>, SetOptions>())
+ return 1;
+ if(!boost::container::test::test_emplace<flat_multiset<test::EmplaceInt>, SetOptions>())
+ return 1;
+
+ if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_set<int> >())
+ return 1;
+
+ if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_multiset<int> >())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_flat_set>())
+ return 1;
+
+ if(!boost::container::test::test_propagate_allocator<boost_container_flat_multiset>())
+ return 1;
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::flat_set<int> cont_int;
+ cont_int a; a.insert(0); a.insert(1); a.insert(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+ {
+ typedef boost::container::flat_multiset<int> cont_int;
+ cont_int a; a.insert(0); a.insert(1); a.insert(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::dtl::identity<int> key_of_value_t;
+ // flat_set, default
+ {
+ typedef boost::container::flat_set<int> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_set, vector
+ {
+ typedef boost::container::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_set, std::vector
+ {
+ typedef std::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_set, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, default
+ {
+ typedef boost::container::flat_multiset<int> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, default) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, vector
+ {
+ typedef boost::container::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // flat_multiset, std::vector
+ {
+ typedef std::vector<int> alloc_or_cont_t;
+ typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont;
+ typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(flat_multiset, std::vector) test failed" << std::endl;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
+
diff --git a/src/boost/libs/container/test/flat_tree_test.cpp b/src/boost/libs/container/test/flat_tree_test.cpp
new file mode 100644
index 000000000..e94c0892b
--- /dev/null
+++ b/src/boost/libs/container/test/flat_tree_test.cpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/flat_tree.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/static_vector.hpp>
+
+#include <iostream>
+
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+using namespace boost::container;
+
+typedef boost::container::dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+namespace dtl {
+
+template class flat_tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator<pair_t>
+ >;
+
+template class flat_tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::allocator<pair_t>
+ >;
+
+template class flat_tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , small_vector<pair_t, 10>
+ >;
+
+template class flat_tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , stable_vector<pair_t>
+ >;
+
+template class flat_tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator<test::movable_and_copyable_int>
+ >;
+
+template class flat_tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::allocator<test::movable_and_copyable_int>
+ >;
+
+template class flat_tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , small_vector<test::movable_and_copyable_int, 10>
+ >;
+
+template class flat_tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , stable_vector<test::movable_and_copyable_int>
+ >;
+
+template class flat_tree
+< test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , static_vector<test::movable_and_copyable_int, 10>
+>;
+
+} //dtl {
+}} //boost::container
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+namespace dtl{
+
+template class flat_tree
+< test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::vector<test::movable_and_copyable_int>
+>;
+
+template class flat_tree
+< pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::vector<pair_t>
+>;
+
+} //dtl {
+}} //boost::container
+
+#endif
+
+int main ()
+{
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default
+ {
+ typedef boost::container::dtl::flat_tree<int, boost::container::dtl::identity<int>,
+ std::less<int>, void> tree;
+ typedef tree::container_type container_type;
+ typedef tree::key_compare key_compare;
+ if (boost::has_trivial_destructor_after_move<tree>::value !=
+ boost::has_trivial_destructor_after_move<container_type>::value &&
+ boost::has_trivial_destructor_after_move<key_compare>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::dtl::flat_tree<int, boost::container::dtl::identity<int>,
+ std::less<int>, std::allocator<int> > tree;
+ typedef tree::container_type container_type;
+ typedef tree::key_compare key_compare;
+ if (boost::has_trivial_destructor_after_move<tree>::value !=
+ boost::has_trivial_destructor_after_move<container_type>::value &&
+ boost::has_trivial_destructor_after_move<key_compare>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/global_resource_test.cpp b/src/boost/libs/container/test/global_resource_test.cpp
new file mode 100644
index 000000000..bb6e96837
--- /dev/null
+++ b/src/boost/libs/container/test/global_resource_test.cpp
@@ -0,0 +1,127 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+
+#include "derived_from_memory_resource.hpp"
+
+#include <cstdlib>
+#include <new>
+
+using namespace boost::container;
+using namespace boost::container::pmr;
+
+#ifdef BOOST_MSVC
+#pragma warning (push)
+#pragma warning (disable : 4290)
+#endif
+
+#if __cplusplus >= 201103L
+#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
+#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER noexcept
+#else
+#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER throw(std::bad_alloc)
+#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER throw()
+#endif
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 50000)
+#pragma GCC diagnostic ignored "-Wsized-deallocation"
+#endif
+
+//ASAN does not support operator new overloading
+#ifndef BOOST_CONTAINER_ASAN
+
+std::size_t allocation_count = 0;
+
+void* operator new[](std::size_t count) BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
+{
+ ++allocation_count;
+ return std::malloc(count);
+}
+
+void operator delete[](void *p) BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER
+{
+ --allocation_count;
+ return std::free(p);
+}
+
+#endif //BOOST_CONTAINER_ASAN
+
+#ifdef BOOST_MSVC
+#pragma warning (pop)
+#endif
+
+#ifndef BOOST_CONTAINER_ASAN
+
+void test_new_delete_resource()
+{
+ //Make sure new_delete_resource calls new[]/delete[]
+ std::size_t memcount = allocation_count;
+ memory_resource *mr = new_delete_resource();
+ //each time should return the same pointer
+ BOOST_TEST(mr == new_delete_resource());
+ #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL
+ BOOST_TEST(memcount == allocation_count);
+ #endif
+ void *addr = mr->allocate(16, 1);
+ #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING) //No new delete replacement possible new_delete is a DLL
+ BOOST_TEST((allocation_count - memcount) == 1);
+ #endif
+ mr->deallocate(addr, 16, 1);
+ BOOST_TEST(memcount == allocation_count);
+}
+
+#endif //BOOST_CONTAINER_ASAN
+
+void test_null_memory_resource()
+{
+ //Make sure it throw or returns null
+ memory_resource *mr = null_memory_resource();
+ #if !defined(BOOST_NO_EXCEPTIONS)
+ bool bad_allocexception_thrown = false;
+ try{
+ mr->allocate(1, 1);
+ }
+ catch(std::bad_alloc&) {
+ bad_allocexception_thrown = true;
+ }
+ catch(...) {
+ }
+ BOOST_TEST(bad_allocexception_thrown == true);
+ #else
+ BOOST_TEST(0 == mr->allocate(1, 1));
+ #endif
+}
+
+void test_default_resource()
+{
+ //Default resource must be new/delete before set_default_resource
+ BOOST_TEST(get_default_resource() == new_delete_resource());
+ //Set default resource and obtain previous
+ derived_from_memory_resource d;
+ memory_resource *prev_default = set_default_resource(&d);
+ BOOST_TEST(get_default_resource() == &d);
+ //Set default resource with null, which should be new/delete
+ prev_default = set_default_resource(0);
+ BOOST_TEST(prev_default == &d);
+ BOOST_TEST(get_default_resource() == new_delete_resource());
+}
+
+int main()
+{
+ #ifndef BOOST_CONTAINER_ASAN
+ test_new_delete_resource();
+ #endif
+ test_null_memory_resource();
+ test_default_resource();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/hash_table_test.cppx b/src/boost/libs/container/test/hash_table_test.cppx
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/boost/libs/container/test/hash_table_test.cppx
diff --git a/src/boost/libs/container/test/input_from_forward_iterator.hpp b/src/boost/libs/container/test/input_from_forward_iterator.hpp
new file mode 100644
index 000000000..9436ceffa
--- /dev/null
+++ b/src/boost/libs/container/test/input_from_forward_iterator.hpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
+#define BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
+
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class FwdIterator>
+class input_iterator_wrapper
+ : public boost::container::iterator< std::input_iterator_tag
+ , typename boost::container::iterator_traits<FwdIterator>::value_type
+ , typename boost::container::iterator_traits<FwdIterator>::difference_type
+ , typename boost::container::iterator_traits<FwdIterator>::pointer
+ , typename boost::container::iterator_traits<FwdIterator>::reference
+ >
+{
+ FwdIterator m_it;
+
+ public:
+ input_iterator_wrapper()
+ : m_it(0)
+ {}
+
+ explicit input_iterator_wrapper(FwdIterator it)
+ : m_it(it)
+ {}
+
+ //Default copy constructor...
+ //input_iterator_wrapper(const input_iterator_wrapper&);
+
+ //Default assignment...
+ //input_iterator_wrapper &operator=(const input_iterator_wrapper&);
+
+ //Default destructor...
+ //~input_iterator_wrapper();
+
+ typename boost::container::iterator_traits<FwdIterator>::reference operator*() const
+ { return *m_it; }
+
+ typename boost::container::iterator_traits<FwdIterator>::pointer operator->() const
+ { return m_it.operator->(); }
+
+ input_iterator_wrapper& operator++()
+ { ++m_it; return *this; }
+
+ input_iterator_wrapper operator++(int )
+ {
+ input_iterator_wrapper tmp(m_it);
+ ++m_it;
+ return tmp;
+ }
+
+ friend bool operator==(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
+ { return left.m_it == right.m_it; }
+
+ friend bool operator!=(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
+ { return left.m_it != right.m_it; }
+};
+
+template<class FwdIterator>
+input_iterator_wrapper<FwdIterator> make_input_from_forward_iterator(const FwdIterator &it)
+{ return input_iterator_wrapper<FwdIterator>(it); }
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#endif //BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
diff --git a/src/boost/libs/container/test/insert_test.hpp b/src/boost/libs/container/test/insert_test.hpp
new file mode 100644
index 000000000..cb862f3c5
--- /dev/null
+++ b/src/boost/libs/container/test/insert_test.hpp
@@ -0,0 +1,75 @@
+#ifndef BOOST_CONTAINER_TEST_INSERT_TEST_HPP
+#define BOOST_CONTAINER_TEST_INSERT_TEST_HPP
+
+// Copyright (C) 2013 Cromwell D. Enage
+// 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)
+
+#include <deque>
+#include <boost/core/lightweight_test.hpp>
+#include "check_equal_containers.hpp"
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<class SeqContainer>
+void
+ test_insert_range(
+ std::deque<int> &std_deque
+ , SeqContainer &seq_container
+ , std::deque<int> const& input_deque
+ , std::size_t index
+ )
+{
+ BOOST_TEST(CheckEqualContainers(std_deque, seq_container));
+
+ std_deque.insert(
+ std_deque.begin() + index
+ , input_deque.begin()
+ , input_deque.end()
+ );
+
+ seq_container.insert(
+ seq_container.begin() + index
+ , input_deque.begin()
+ , input_deque.end()
+ );
+ BOOST_TEST(CheckEqualContainers(std_deque, seq_container));
+}
+
+template<class SeqContainer>
+bool test_range_insertion()
+{
+ int err_count = boost::report_errors();
+ typedef typename SeqContainer::value_type value_type;
+ std::deque<int> input_deque;
+ for (int element = -10; element < 10; ++element)
+ {
+ input_deque.push_back(element + 20);
+ }
+
+ for (std::size_t i = 0; i <= input_deque.size(); ++i)
+ {
+ std::deque<int> std_deque;
+ ::boost::movelib::unique_ptr<SeqContainer> const pseqcontainer = ::boost::movelib::make_unique<SeqContainer>();
+ SeqContainer &seq_container = *pseqcontainer;
+
+ for (int element = -10; element < 10; ++element)
+ {
+ std_deque.push_back(element);
+ seq_container.push_back(value_type(element));
+ }
+ test_insert_range(std_deque, seq_container, input_deque, i);
+ }
+
+ return err_count == boost::report_errors();
+}
+
+
+} //namespace test {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_TEST_INSERT_TEST_HPP
diff --git a/src/boost/libs/container/test/insert_vs_emplace_test.cpp b/src/boost/libs/container/test/insert_vs_emplace_test.cpp
new file mode 100644
index 000000000..b91a693c5
--- /dev/null
+++ b/src/boost/libs/container/test/insert_vs_emplace_test.cpp
@@ -0,0 +1,498 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2014.
+// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This testcase is based on H. Hinnant's article "Insert vs. Emplace",
+// (http://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html)
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <iostream>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X
+{
+ int i_;
+ int* p_;
+
+ BOOST_COPYABLE_AND_MOVABLE(X)
+
+public:
+ struct special
+ {
+ unsigned c;
+ unsigned dt;
+ unsigned cc;
+ unsigned ca;
+ unsigned mc;
+ unsigned ma;
+
+ friend bool operator==(const special &l, const special &r)
+ { return l.c == r.c && l.dt == r.dt && l.cc == r.cc && l.ca == r.ca && l.mc == r.mc && l.ma == r.ma; }
+ };
+ static special sp;
+
+ X(int i, int* p)
+ : i_(i)
+ , p_(p)
+ {
+// std::cout << "X(int i, int* p)\n";
+ sp.c++;
+ }
+
+ ~X()
+ {
+// std::cout << "~X()\n";
+ sp.dt++;
+ }
+
+ X(const X& x)
+ : i_(x.i_)
+ , p_(x.p_)
+ {
+// std::cout << "X(const X& x)\n";
+ sp.cc++;
+ }
+
+ X& operator=(BOOST_COPY_ASSIGN_REF(X) x)
+ {
+
+ i_ = x.i_;
+ p_ = x.p_;
+// std::cout << "X& operator=(const X& x)\n";
+ sp.ca++;
+ return *this;
+ }
+
+ X(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
+ : i_(x.i_)
+ , p_(x.p_)
+ {
+// std::cout << "X(X&& x)\n";
+ sp.mc++;
+ }
+
+ X& operator=(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+
+ i_ = x.i_;
+ p_ = x.p_;
+// std::cout << "X& operator=(X&& x)\n";
+ sp.ma++;
+ return *this;
+ }
+
+};
+
+std::ostream&
+operator<<(std::ostream& os, X::special const& sp)
+{
+ os << "Const: " << sp.c << '\n';
+ os << "Destr: " << sp.dt << '\n';
+ os << "CopyC: " << sp.cc << '\n';
+ os << "CopyA: " << sp.ca << '\n';
+ os << "MoveC: " << sp.mc << '\n';
+ os << "MoveA: " << sp.ma << '\n';
+ os << "Total: " << (sp.c + sp.dt + sp.cc + sp.ca + sp.mc + sp.ma) << '\n';
+ return os;
+}
+
+X::special X::sp = X::special();
+
+const X produce_const_prvalue()
+{ return X(0, 0); }
+
+int main()
+{
+ X::special insert_results;
+ X::special emplace_results;
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--insert lvalue no reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace lvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--insert xvalue no reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace xvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace const prvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), produce_const_prvalue());
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace const prvalue no reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), produce_const_prvalue());
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--insert rvalue no reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--emplace rvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ //With emulated move semantics an extra copy is unavoidable
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ #endif
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--insert lvalue reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace lvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--insert xvalue reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace xvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--insert rvalue reallocation--\n";
+ X::sp = X::special();
+ v.insert(v.begin(), X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--emplace rvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace(v.begin(), X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ //With emulated move semantics an extra copy is unavoidable
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ #endif
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--push_back lvalue no reallocation--\n";
+ X::sp = X::special();
+ v.push_back(x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace_back lvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--push_back xvalue no reallocation--\n";
+ X::sp = X::special();
+ v.push_back(boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace_back xvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--push_back rvalue no reallocation--\n";
+ X::sp = X::special();
+ v.push_back(X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(4);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--emplace_back rvalue no reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ //With emulated move semantics an extra copy is unavoidable
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ #endif
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--push_back lvalue reallocation--\n";
+ X::sp = X::special();
+ v.push_back(x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace_back lvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(x);
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--push_back xvalue reallocation--\n";
+ X::sp = X::special();
+ v.push_back(boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ X x(0,0);
+ std::cout << "--emplace_back xvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(boost::move(x));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--push_back rvalue reallocation--\n";
+ X::sp = X::special();
+ v.push_back(X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ insert_results = X::sp;
+ }
+ {
+ boost::container::vector<X> v;
+ v.reserve(3);
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ v.push_back(X(0,0));
+ std::cout << "--emplace_back rvalue reallocation--\n";
+ X::sp = X::special();
+ v.emplace_back(X(0,0));
+ std::cout << X::sp;
+ std::cout << "----\n";
+ emplace_results = X::sp;
+ }
+ //With emulated move semantics an extra copy is unavoidable
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_TEST_EQ(insert_results == emplace_results, true);
+ #endif
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/list_test.cpp b/src/boost/libs/container/test/list_test.cpp
new file mode 100644
index 000000000..c4f9f41d4
--- /dev/null
+++ b/src/boost/libs/container/test/list_test.cpp
@@ -0,0 +1,286 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include "dummy_test_allocator.hpp"
+#include <memory>
+#include "movable_int.hpp"
+#include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::list
+ < test::movable_and_copyable_int
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::list
+ < test::movable_and_copyable_int
+ , adaptive_pool<test::movable_and_copyable_int> >;
+
+namespace dtl {
+
+template class iterator_from_iiterator
+ <intrusive_list_type< std::allocator<int> >::container_type::iterator, true >;
+template class iterator_from_iiterator
+ <intrusive_list_type< std::allocator<int> >::container_type::iterator, false>;
+
+}
+
+}}
+
+class recursive_list
+{
+public:
+ int id_;
+ list<recursive_list> list_;
+ list<recursive_list>::iterator it_;
+ list<recursive_list>::const_iterator cit_;
+ list<recursive_list>::reverse_iterator rit_;
+ list<recursive_list>::const_reverse_iterator crit_;
+
+ recursive_list &operator=(const recursive_list &o)
+ { list_ = o.list_; return *this; }
+};
+
+void recursive_list_test()//Test for recursive types
+{
+ list<recursive_list> recursive, copy;
+ //Test to test both move emulations
+ if(!copy.size()){
+ copy = recursive;
+ }
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef list< ValueType
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ > type;
+ };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+ if(test::list_test<MyCont, true>())
+ return 1;
+ if(test::list_test<MyMoveCont, true>())
+ return 1;
+ if(test::list_test<MyCopyMoveCont, true>())
+ return 1;
+ if(test::list_test<MyCopyMoveCont, true>())
+ return 1;
+ if(test::list_test<MyCopyCont, true>())
+ return 1;
+
+ return 0;
+}
+
+bool test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ const std::initializer_list<int> il = {1, 10};
+ const list<int> expectedList(il.begin(), il.end());
+
+ const list<int> testConstructor((il));
+ if(testConstructor != expectedList)
+ return false;
+
+ const list<int> testConstructorAllocator(il, list<int>::allocator_type());
+ if (testConstructorAllocator != expectedList)
+ return false;
+
+ list<int> testAssignOperator = {10, 11};
+ testAssignOperator = il;
+ if(testAssignOperator != expectedList)
+ return false;
+
+ list<int> testAssignMethod = {99};
+ testAssignMethod = il;
+ if(testAssignMethod != expectedList)
+ return false;
+
+ list<int> testInsertMethod;
+ testInsertMethod.insert(testInsertMethod.cbegin(), il);
+ if(testInsertMethod != testInsertMethod)
+ return false;
+
+ return true;
+#endif
+ return true;
+}
+
+struct boost_container_list;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_list>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::list<T, Allocator> type;
+ };
+};
+
+}}} //namespace boost::container::test
+
+int main ()
+{
+ recursive_list_test();
+ {
+ //Now test move semantics
+ list<recursive_list> original;
+ list<recursive_list> move_ctor(boost::move(original));
+ list<recursive_list> move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+ }
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ // int variants
+ if (test::list_test<list<int, std::allocator<int> >, true>())
+ return 1;
+ if (test::list_test<list<int>, true>())
+ return 1;
+ if (test::list_test<list<int, adaptive_pool<int> >, true>())
+ return 1;
+ if (test::list_test<list<test::movable_int>, true>())
+ return 1;
+ if (test::list_test<list<test::movable_and_copyable_int>, true>())
+ return 1;
+ if (test::list_test<list<test::copyable_int>, true>())
+ return 1;
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
+
+ if(!boost::container::test::test_emplace<list<test::EmplaceInt>, Options>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_list>())
+ return 1;
+
+ ////////////////////////////////////
+ // Initializer lists
+ ////////////////////////////////////
+ if(!test_support_for_initializer_list())
+ return 1;
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::list<int> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction Tests
+ ////////////////////////////////////
+ {
+ auto gold = std::list{ 1, 2, 3 };
+ auto test = boost::container::list(gold.begin(), gold.end());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (test.front() != 1)
+ return 1;
+ test.pop_front();
+ if (test.front() != 2)
+ return 1;
+ test.pop_front();
+ if (test.front() != 3)
+ return 1;
+ test.pop_front();
+ }
+ {
+ auto gold = std::list{ 1, 2, 3 };
+ auto test = boost::container::list(gold.begin(), gold.end(), new_allocator<int>());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (test.front() != 1)
+ return 1;
+ test.pop_front();
+ if (test.front() != 2)
+ return 1;
+ test.pop_front();
+ if (test.front() != 3)
+ return 1;
+ test.pop_front();
+ }
+#endif
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::list<int> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::list<int, std::allocator<int> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/list_test.hpp b/src/boost/libs/container/test/list_test.hpp
new file mode 100644
index 000000000..9640ec099
--- /dev/null
+++ b/src/boost/libs/container/test/list_test.hpp
@@ -0,0 +1,469 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_LIST_TEST_HEADER
+#define BOOST_CONTAINER_TEST_LIST_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include "input_from_forward_iterator.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+
+#include <list>
+#include <functional> //std::greater
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class V1, class V2>
+bool list_copyable_only(V1 &, V2 &, boost::container::dtl::false_type)
+{
+ return true;
+}
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool list_copyable_only(V1 &boostlist, V2 &stdlist, boost::container::dtl::true_type)
+{
+ typedef typename V1::value_type IntType;
+ boostlist.insert(boostlist.end(), 50, IntType(1));
+ stdlist.insert(stdlist.end(), 50, 1);
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+
+ {
+ IntType move_me(1);
+ boostlist.insert(boostlist.begin(), 50, boost::move(move_me));
+ stdlist.insert(stdlist.begin(), 50, 1);
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+ }
+ {
+ IntType move_me(2);
+ boostlist.assign(boostlist.size()/2, boost::move(move_me));
+ stdlist.assign(stdlist.size()/2, 2);
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+ }
+ {
+ IntType move_me(3);
+ boostlist.assign(boostlist.size()*3-1, boost::move(move_me));
+ stdlist.assign(stdlist.size()*3-1, 3);
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+ }
+
+ {
+ IntType copy_me(3);
+ const IntType ccopy_me(3);
+ boostlist.push_front(copy_me);
+ stdlist.push_front(int(3));
+ boostlist.push_front(ccopy_me);
+ stdlist.push_front(int(3));
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+ }
+ { //List(const List &)
+ ::boost::movelib::unique_ptr<V1> const pv1 = ::boost::movelib::make_unique<V1>(boostlist);
+ ::boost::movelib::unique_ptr<V2> const pv2 = ::boost::movelib::make_unique<V2>(stdlist);
+
+ V1 &v1 = *pv1;
+ V2 &v2 = *pv2;
+
+ boostlist.clear();
+ stdlist.clear();
+ boostlist.assign(v1.begin(), v1.end());
+ stdlist.assign(v2.begin(), v2.end());
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+ }
+ { //List(const List &, alloc)
+ ::boost::movelib::unique_ptr<V1> const pv1 = ::boost::movelib::make_unique<V1>(boostlist, typename V1::allocator_type());
+ ::boost::movelib::unique_ptr<V2> const pv2 = ::boost::movelib::make_unique<V2>(stdlist);
+
+ V1 &v1 = *pv1;
+ V2 &v2 = *pv2;
+
+ boostlist.clear();
+ stdlist.clear();
+ boostlist.assign(v1.begin(), v1.end());
+ stdlist.assign(v2.begin(), v2.end());
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+ }
+
+ return true;
+}
+
+template<bool DoublyLinked>
+struct list_push_data_function
+{
+ template<class MyBoostList, class MyStdList>
+ static int execute(int max, MyBoostList &boostlist, MyStdList &stdlist)
+ {
+ typedef typename MyBoostList::value_type IntType;
+ for(int i = 0; i < max; ++i){
+ IntType move_me(i);
+ boostlist.push_back(boost::move(move_me));
+ stdlist.push_back(i);
+ boostlist.push_front(IntType(i));
+ stdlist.push_front(int(i));
+ }
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ return 0;
+ }
+};
+
+template<>
+struct list_push_data_function<false>
+{
+ template<class MyBoostList, class MyStdList>
+ static int execute(int max, MyBoostList &boostlist, MyStdList &stdlist)
+ {
+ typedef typename MyBoostList::value_type IntType;
+ for(int i = 0; i < max; ++i){
+ IntType move_me(i);
+ boostlist.push_front(boost::move(move_me));
+ stdlist.push_front(i);
+ boostlist.push_front(IntType(i));
+ stdlist.push_front(int(i));
+ }
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ return 0;
+ }
+};
+
+template<bool DoublyLinked>
+struct list_pop_back_function
+{
+ template<class MyStdList, class MyBoostList>
+ static int execute(MyBoostList &boostlist, MyStdList &stdlist)
+ {
+ boostlist.pop_back();
+ stdlist.pop_back();
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ return 0;
+ }
+};
+
+template<>
+struct list_pop_back_function<false>
+{
+ template<class MyStdList, class MyBoostList>
+ static int execute(MyBoostList &boostlist, MyStdList &stdlist)
+ {
+ (void)boostlist; (void)stdlist;
+ return 0;
+ }
+};
+
+template<class MyBoostList
+ ,bool DoublyLinked>
+int list_test (bool copied_allocators_equal = true)
+{
+ typedef std::list<int> MyStdList;
+ typedef typename MyBoostList::value_type IntType;
+ const int max = 100;
+ typedef list_push_data_function<DoublyLinked> push_data_t;
+
+ { //List(n)
+ ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>(100);
+ ::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>(100);
+ if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1;
+ }
+ { //List(n, alloc)
+ ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>(100, typename MyBoostList::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>(100);
+ if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1;
+ }
+ { //List(List &&)
+ ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>(::boost::move(*boostlistp));
+ if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+ }
+ { //List(List &&, alloc)
+ ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>
+ (::boost::move(*boostlistp), typename MyBoostList::allocator_type());
+ if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+ }
+ { //List operator=(List &&)
+ ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+ ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>();
+ *boostlistp2 = ::boost::move(*boostlistp);
+ if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+ }
+
+ ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>();
+ ::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>();
+
+ MyBoostList &boostlist = *pboostlist;
+ MyStdList &stdlist = *pstdlist;
+
+ if(push_data_t::execute(max, boostlist, stdlist)){
+ return 1;
+ }
+
+ boostlist.erase(boostlist.begin()++);
+ stdlist.erase(stdlist.begin()++);
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ if(list_pop_back_function<DoublyLinked>::execute(boostlist, stdlist)){
+ return 1;
+ }
+
+ boostlist.pop_front();
+ stdlist.pop_front();
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ boostlist.assign(boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(&aux_vect[50]));
+ stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ boostlist.assign(boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+ ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
+ stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+ }
+
+ if(copied_allocators_equal){
+ boostlist.sort();
+ stdlist.sort();
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+ }
+
+ boostlist.reverse();
+ stdlist.reverse();
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ boostlist.reverse();
+ stdlist.reverse();
+ if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ typename MyBoostList::iterator old_begin = boostlist.begin();
+ typename MyBoostList::iterator it_insert =
+ boostlist.insert(boostlist.begin()
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(&aux_vect[50]));
+ if(it_insert != boostlist.begin() || boost::container::iterator_distance(it_insert, old_begin) != 50)
+ return 1;
+
+ stdlist.insert(stdlist.begin(), &aux_vect2[0], &aux_vect2[50]);
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+
+ old_begin = boostlist.begin();
+ it_insert = boostlist.insert(boostlist.end()
+ ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+ ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
+ if(boost::container::iterator_distance(it_insert, boostlist.end()) != 50)
+ return 1;
+ stdlist.insert(stdlist.end(), &aux_vect2[0], &aux_vect2[50]);
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ }
+
+ boostlist.unique();
+ stdlist.unique();
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+
+ if(copied_allocators_equal){
+ boostlist.sort(std::greater<IntType>());
+ stdlist.sort(std::greater<int>());
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ }
+
+ for(int i = 0; i < max; ++i){
+ IntType new_int(i);
+ boostlist.insert(boostlist.end(), boost::move(new_int));
+ stdlist.insert(stdlist.end(), i);
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+ }
+ if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+
+ boostlist.resize(25);
+ stdlist.resize(25);
+ boostlist.resize(50);
+ stdlist.resize(50);
+ boostlist.resize(0);
+ stdlist.resize(0);
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+
+ //some comparison operators
+ if(!(boostlist == boostlist))
+ return 1;
+ if(boostlist != boostlist)
+ return 1;
+ if(boostlist < boostlist)
+ return 1;
+ if(boostlist > boostlist)
+ return 1;
+ if(!(boostlist <= boostlist))
+ return 1;
+ if(!(boostlist >= boostlist))
+ return 1;
+
+ if(push_data_t::execute(max, boostlist, stdlist)){
+ return 1;
+ }
+ {
+ MyBoostList otherboostlist(boostlist.get_allocator());
+ MyStdList otherstdlist;
+
+ int listsize = (int)boostlist.size();
+
+ if(push_data_t::execute(listsize, boostlist, stdlist)){
+ return 1;
+ }
+
+ if(copied_allocators_equal){
+ boostlist.splice(boostlist.begin(), otherboostlist);
+ stdlist.splice(stdlist.begin(), otherstdlist);
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ }
+
+ listsize = (int)boostlist.size();
+
+ if(push_data_t::execute(listsize, boostlist, stdlist)){
+ return 1;
+ }
+
+ if(push_data_t::execute(listsize, otherboostlist, otherstdlist)){
+ return 1;
+ }
+
+ if(copied_allocators_equal){
+ boostlist.sort(std::greater<IntType>());
+ stdlist.sort(std::greater<int>());
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+
+ otherboostlist.sort(std::greater<IntType>());
+ otherstdlist.sort(std::greater<int>());
+ if(!CheckEqualContainers(otherboostlist, otherstdlist))
+ return 1;
+
+ boostlist.merge(otherboostlist, std::greater<IntType>());
+ stdlist.merge(otherstdlist, std::greater<int>());
+ if(!CheckEqualContainers(boostlist, stdlist))
+ return 1;
+ }
+
+ if(!list_copyable_only(boostlist, stdlist
+ ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+template<class List>
+bool test_list_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ const std::initializer_list<int> il = {5, 10, 15};
+ const List expected_list(il.begin(), il.end());
+ {
+ List sl = il;
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ List sl = {1, 2};
+ sl = il;
+ if(sl != expected_list)
+ return false;
+ }
+ {
+ List sl({ 1, 2 }, typename List::allocator_type());
+ sl = il;
+ if (sl != expected_list)
+ return false;
+ }
+ {
+ List sl = {4, 5};
+ sl.assign(il);
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ List sl = {15};
+ sl.insert(sl.cbegin(), {5, 10});
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ List sl = {5};
+ sl.insert_after(sl.cbegin(), {10, 15});
+ if(sl != expected_list)
+ return false;
+ }
+ return true;
+#endif
+ return true;
+}
+
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/src/boost/libs/container/test/map_test.cpp b/src/boost/libs/container/test/map_test.cpp
new file mode 100644
index 000000000..74483037d
--- /dev/null
+++ b/src/boost/libs/container/test/map_test.cpp
@@ -0,0 +1,693 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include <map>
+
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+class recursive_map
+{
+ public:
+ recursive_map & operator=(const recursive_map &x)
+ { id_ = x.id_; map_ = x.map_; return *this; }
+
+ int id_;
+ map<recursive_map, recursive_map> map_;
+ map<recursive_map, recursive_map>::iterator it_;
+ map<recursive_map, recursive_map>::const_iterator cit_;
+ map<recursive_map, recursive_map>::reverse_iterator rit_;
+ map<recursive_map, recursive_map>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_map &a, const recursive_map &b)
+ { return a.id_ < b.id_; }
+};
+
+class recursive_multimap
+{
+ public:
+ recursive_multimap & operator=(const recursive_multimap &x)
+ { id_ = x.id_; multimap_ = x.multimap_; return *this; }
+
+ int id_;
+ multimap<recursive_multimap, recursive_multimap> multimap_;
+ multimap<recursive_multimap, recursive_multimap>::iterator it_;
+ multimap<recursive_multimap, recursive_multimap>::const_iterator cit_;
+ multimap<recursive_multimap, recursive_multimap>::reverse_iterator rit_;
+ multimap<recursive_multimap, recursive_multimap>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_multimap &a, const recursive_multimap &b)
+ { return a.id_ < b.id_; }
+};
+
+template<class C>
+void test_move()
+{
+ //Now test move semantics
+ C original;
+ original.emplace();
+ C move_ctor(boost::move(original));
+ C move_assign;
+ move_assign.emplace();
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+}
+
+bool node_type_test()
+{
+ using namespace boost::container;
+ {
+ typedef map<test::movable_int, test::movable_int> map_type;
+ map_type src;
+ {
+ test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13);
+ src.try_emplace(boost::move(mv_1), boost::move(mv_11));
+ src.try_emplace(boost::move(mv_2), boost::move(mv_12));
+ src.try_emplace(boost::move(mv_3), boost::move(mv_13));
+ }
+ if(src.size() != 3)
+ return false;
+
+ map_type dst;
+ {
+ test::movable_int mv_3(3), mv_33(33);
+ dst.try_emplace(boost::move(mv_3), boost::move(mv_33));
+ }
+
+ if(dst.size() != 1)
+ return false;
+
+ const test::movable_int mv_1(1);
+ const test::movable_int mv_2(2);
+ const test::movable_int mv_3(3);
+ const test::movable_int mv_33(33);
+ const test::movable_int mv_13(13);
+ map_type::insert_return_type r;
+
+ r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
+ if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
+ return false;
+ r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
+ if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
+ return false;
+ r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
+ if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
+ return false;
+ r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
+
+ if(!src.empty())
+ return false;
+ if(dst.size() != 3)
+ return false;
+ if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.key() == mv_3 && r.node.mapped() == mv_13) )
+ return false;
+ }
+
+ {
+ typedef multimap<test::movable_int, test::movable_int> multimap_type;
+ multimap_type src;
+ {
+ test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3), mv_11(11), mv_12(12), mv_13(13), mv_23(23);
+ src.emplace(boost::move(mv_1), boost::move(mv_11));
+ src.emplace(boost::move(mv_2), boost::move(mv_12));
+ src.emplace(boost::move(mv_3), boost::move(mv_13));
+ src.emplace_hint(src.begin(), boost::move(mv_3bis), boost::move(mv_23));
+ }
+ if(src.size() != 4)
+ return false;
+
+ multimap_type dst;
+ {
+ test::movable_int mv_3(3), mv_33(33);
+ dst.emplace(boost::move(mv_3), boost::move(mv_33));
+ }
+
+ if(dst.size() != 1)
+ return false;
+
+ const test::movable_int mv_1(1);
+ const test::movable_int mv_2(2);
+ const test::movable_int mv_3(3);
+ const test::movable_int mv_4(4);
+ const test::movable_int mv_33(33);
+ const test::movable_int mv_13(13);
+ const test::movable_int mv_23(23);
+ multimap_type::iterator r;
+
+ multimap_type::node_type nt(src.extract(mv_3));
+ r = dst.insert(dst.begin(), boost::move(nt));
+ if(! (r->first == mv_3 && r->second == mv_23 && dst.find(mv_3) == r && nt.empty()) )
+ return false;
+
+ nt = src.extract(src.find(mv_1));
+ r = dst.insert(boost::move(nt)); // Iterator version, successful
+ if(! (r->first == mv_1 && nt.empty()) )
+ return false;
+
+ nt = src.extract(mv_2);
+ r = dst.insert(boost::move(nt)); // Key type version, successful
+ if(! (r->first == mv_2 && nt.empty()) )
+ return false;
+
+ r = dst.insert(src.extract(mv_3)); // Key type version, successful
+ if(! (r->first == mv_3 && r->second == mv_13 && r == --multimap_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
+ return false;
+
+ r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
+ if(! (r == dst.end()) )
+ return false;
+
+ if(!src.empty())
+ return false;
+ if(dst.size() != 5)
+ return false;
+ }
+ return true;
+}
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+struct GetAllocatorMap
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef map< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
+ , typename boost::container::tree_assoc_options
+ < boost::container::tree_type<tree_type_value>
+ >::type
+ > map_type;
+
+ typedef multimap< ValueType
+ , ValueType
+ , std::less<ValueType>
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
+ , typename boost::container::tree_assoc_options
+ < boost::container::tree_type<tree_type_value>
+ >::type
+ > multimap_type;
+ };
+};
+
+struct boost_container_map;
+struct boost_container_multimap;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_map>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef typename boost::container::allocator_traits<Allocator>::
+ template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
+ typedef boost::container::map<T, T, std::less<T>, TypeAllocator> type;
+ };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_multimap>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef typename boost::container::allocator_traits<Allocator>::
+ template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
+ typedef boost::container::multimap<T, T, std::less<T>, TypeAllocator> type;
+ };
+};
+
+void test_merge_from_different_comparison()
+{
+ map<int, int> map1;
+ map<int, int, std::greater<int> > map2;
+ map1.merge(map2);
+}
+
+bool test_heterogeneous_lookups()
+{
+ typedef map<int, char, less_transparent> map_t;
+ typedef multimap<int, char, less_transparent> mmap_t;
+ typedef map_t::value_type value_type;
+
+ map_t map1;
+ mmap_t mmap1;
+
+ const map_t &cmap1 = map1;
+ const mmap_t &cmmap1 = mmap1;
+
+ if(!map1.insert_or_assign(1, 'a').second)
+ return false;
+ if( map1.insert_or_assign(1, 'b').second)
+ return false;
+ if(!map1.insert_or_assign(2, 'c').second)
+ return false;
+ if( map1.insert_or_assign(2, 'd').second)
+ return false;
+ if(!map1.insert_or_assign(3, 'e').second)
+ return false;
+
+ if(map1.insert_or_assign(1, 'a').second)
+ return false;
+ if(map1.insert_or_assign(1, 'b').second)
+ return false;
+ if(map1.insert_or_assign(2, 'c').second)
+ return false;
+ if(map1.insert_or_assign(2, 'd').second)
+ return false;
+ if(map1.insert_or_assign(3, 'e').second)
+ return false;
+
+ mmap1.insert(value_type(1, 'a'));
+ mmap1.insert(value_type(1, 'b'));
+ mmap1.insert(value_type(2, 'c'));
+ mmap1.insert(value_type(2, 'd'));
+ mmap1.insert(value_type(3, 'e'));
+
+ const test::non_copymovable_int find_me(2);
+
+ //find
+ if(map1.find(find_me)->second != 'd')
+ return false;
+ if(cmap1.find(find_me)->second != 'd')
+ return false;
+ if(mmap1.find(find_me)->second != 'c')
+ return false;
+ if(cmmap1.find(find_me)->second != 'c')
+ return false;
+
+ //count
+ if(map1.count(find_me) != 1)
+ return false;
+ if(cmap1.count(find_me) != 1)
+ return false;
+ if(mmap1.count(find_me) != 2)
+ return false;
+ if(cmmap1.count(find_me) != 2)
+ return false;
+
+ //contains
+ if(!map1.contains(find_me))
+ return false;
+ if(!cmap1.contains(find_me))
+ return false;
+ if(!mmap1.contains(find_me))
+ return false;
+ if(!cmmap1.contains(find_me))
+ return false;
+
+ //lower_bound
+ if(map1.lower_bound(find_me)->second != 'd')
+ return false;
+ if(cmap1.lower_bound(find_me)->second != 'd')
+ return false;
+ if(mmap1.lower_bound(find_me)->second != 'c')
+ return false;
+ if(cmmap1.lower_bound(find_me)->second != 'c')
+ return false;
+
+ //upper_bound
+ if(map1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(cmap1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(mmap1.upper_bound(find_me)->second != 'e')
+ return false;
+ if(cmmap1.upper_bound(find_me)->second != 'e')
+ return false;
+
+ //equal_range
+ if(map1.equal_range(find_me).first->second != 'd')
+ return false;
+ if(cmap1.equal_range(find_me).second->second != 'e')
+ return false;
+ if(mmap1.equal_range(find_me).first->second != 'c')
+ return false;
+ if(cmmap1.equal_range(find_me).second->second != 'e')
+ return false;
+
+ return true;
+}
+
+bool constructor_template_auto_deduction_test()
+{
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+ {
+ std::map<int, int> int_map;
+ for(std::size_t i = 0; i != NumElements; ++i){
+ int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+ std::multimap<int, int> int_mmap;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+ }
+
+ typedef std::less<int> comp_int_t;
+ typedef std::allocator<std::pair<const int, int> > alloc_pair_int_t;
+
+ //range
+ {
+ auto fmap = map(int_map.begin(), int_map.end());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(int_mmap.begin(), int_mmap.end());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp
+ {
+ auto fmap = map(int_map.begin(), int_map.end(), comp_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fmap = map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fmap = map(int_map.begin(), int_map.end(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+
+ //ordered_unique_range / ordered_range
+
+ //range
+ {
+ auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end());
+ if(!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end());
+ if(!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp
+ {
+ auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t());
+ if (!CheckEqualContainers(int_map, fmap))
+ return false;
+ auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t());
+ if (!CheckEqualContainers(int_mmap, fmmap))
+ return false;
+ }
+ }
+#endif
+
+ return true;
+}
+
+}}} //namespace boost::container::test
+
+int main ()
+{
+ //Recursive container instantiation
+ {
+ map<recursive_map, recursive_map> map_;
+ multimap<recursive_multimap, recursive_multimap> multimap_;
+ }
+ //Allocator argument container
+ {
+ map<int, int> map_((map<int, int>::allocator_type()));
+ multimap<int, int> multimap_((multimap<int, int>::allocator_type()));
+ }
+ //Now test move semantics
+ {
+ test_move<map<recursive_map, recursive_map> >();
+ test_move<multimap<recursive_multimap, recursive_multimap> >();
+ }
+
+ //Test std::pair value type as tree has workarounds to make old std::pair
+ //implementations movable that can break things
+ {
+ boost::container::map<pair_t, pair_t> s;
+ std::pair<const pair_t,pair_t> p;
+ s.insert(p);
+ s.emplace(p);
+ }
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ {
+ typedef std::map<int, int> MyStdMap;
+ typedef std::multimap<int, int> MyStdMultiMap;
+
+ if (0 != test::map_test
+ < GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<std::allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void>, avl_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<adaptive_pool<void>, scapegoat_tree>" << std::endl;
+ return 1;
+ }
+
+ ///////////
+
+ if (0 != test::map_test
+ < GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void>, splay_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::map_test
+ < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::map_type
+ , MyStdMap
+ , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multimap_type
+ , MyStdMultiMap>()) {
+ std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
+ if(!boost::container::test::test_emplace<map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+ return 1;
+ if(!boost::container::test::test_emplace<multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_map>())
+ return 1;
+
+ if(!boost::container::test::test_propagate_allocator<boost_container_multimap>())
+ return 1;
+
+ if (!boost::container::test::test_map_support_for_initialization_list_for<map<int, int> >())
+ return 1;
+
+ if (!boost::container::test::test_map_support_for_initialization_list_for<multimap<int, int> >())
+ return 1;
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::map<int, int> cont_int;
+ cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+ boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+ {
+ typedef boost::container::multimap<int, int> cont_int;
+ cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+ boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // Node extraction/insertion testing functions
+ ////////////////////////////////////
+ if(!node_type_test())
+ return 1;
+
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction test
+ ////////////////////////////////////
+ if (!test::constructor_template_auto_deduction_test()) {
+ return 1;
+ }
+
+ if (!boost::container::test::instantiate_constructors<map<int, int>, multimap<int, int> >())
+ return 1;
+
+ test::test_merge_from_different_comparison();
+
+ if(!test::test_heterogeneous_lookups())
+ return 1;
+
+ ////////////////////////////////////
+ // Test optimize_size option
+ ////////////////////////////////////
+ //
+ // map
+ //
+ typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+ , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmap_size_optimized_no;
+
+ typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+ , tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlmap_size_optimized_yes;
+ //
+ // multimap
+ //
+ typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+ , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmmap_size_optimized_yes;
+ typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+ , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmmap_size_optimized_no;
+
+ BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes) < sizeof(rbmap_size_optimized_no));
+ BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes) < sizeof(avlmmap_size_optimized_no));
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ {
+ typedef std::pair<const int, int> value_type;
+ //
+ // map
+ //
+ // default allocator
+ {
+ typedef boost::container::map<int, int> cont;
+ typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(map, default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::map<int, int, std::less<int>, std::allocator<value_type> > cont;
+ typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(map, std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ //
+ // multimap
+ //
+ // default allocator
+ {
+ // default allocator
+ typedef boost::container::multimap<int, int> cont;
+ typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(multimap, default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::multimap<int, int, std::less<int>, std::allocator<value_type> > cont;
+ typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(multimap, std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/map_test.hpp b/src/boost/libs/container/test/map_test.hpp
new file mode 100644
index 000000000..160c46ad0
--- /dev/null
+++ b/src/boost/libs/container/test/map_test.hpp
@@ -0,0 +1,1264 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER
+#define BOOST_CONTAINER_TEST_MAP_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include <boost/container/detail/pair.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/make_unique.hpp>
+
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+#include <string>
+#include <iostream>
+
+#include <boost/intrusive/detail/mpl.hpp>
+
+namespace boost { namespace container { namespace test {
+
+BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_member_rebalance, rebalance)
+
+}}}
+
+const int MaxElem = 50;
+
+template<class T1, class T2, class T3, class T4>
+bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2)
+{
+ return p1.first == p2.first && p1.second == p2.second;
+}
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class C>
+void map_test_rebalanceable(C &, boost::container::dtl::false_type)
+{}
+
+template<class C>
+void map_test_rebalanceable(C &c, boost::container::dtl::true_type)
+{
+ c.rebalance();
+}
+
+template<class MyBoostMap
+ ,class MyStdMap
+ ,class MyBoostMultiMap
+ ,class MyStdMultiMap>
+int map_test_copyable(boost::container::dtl::false_type)
+{ return 0; }
+
+template<class MyBoostMap
+ ,class MyStdMap
+ ,class MyBoostMultiMap
+ ,class MyStdMultiMap>
+int map_test_copyable(boost::container::dtl::true_type)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdPairType;
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>();
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>();
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>();
+ MyBoostMap &boostmap = *pboostmap;
+ MyStdMap &stdmap = *pstdmap;
+ MyBoostMultiMap &boostmultimap = *pboostmultimap;
+ MyStdMultiMap &stdmultimap = *pstdmultimap;
+
+ //Just to test move aware catch conversions
+ boostmap.insert(boostmap.cbegin(), boostmap.cend());
+ boostmultimap.insert(boostmultimap.cbegin(), boostmultimap.cend());
+ boostmap.insert(boostmap.begin(), boostmap.end());
+ boostmultimap.insert(boostmultimap.begin(), boostmultimap.end());
+
+ int i;
+ for(i = 0; i < MaxElem; ++i){
+ {
+ IntType i1(i), i2(i);
+ IntPairType intpair1(boost::move(i1), boost::move(i2));
+ boostmap.insert(boost::move(intpair1));
+ stdmap.insert(StdPairType(i, i));
+ }
+ {
+ IntType i1(i), i2(i);
+ IntPairType intpair2(boost::move(i1), boost::move(i2));
+ boostmultimap.insert(boost::move(intpair2));
+ stdmultimap.insert(StdPairType(i, i));
+ }
+ }
+ if(!CheckEqualContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualContainers(boostmultimap, stdmultimap)) return 1;
+ {
+ //Now, test copy constructor
+ MyBoostMap boostmapcopy(boostmap);
+ MyStdMap stdmapcopy(stdmap);
+ MyBoostMultiMap boostmmapcopy(boostmultimap);
+ MyStdMultiMap stdmmapcopy(stdmultimap);
+
+ if(!CheckEqualContainers(boostmapcopy, stdmapcopy))
+ return 1;
+ if(!CheckEqualContainers(boostmmapcopy, stdmmapcopy))
+ return 1;
+
+ //And now assignment
+ boostmapcopy = boostmap;
+ stdmapcopy = stdmap;
+ boostmmapcopy = boostmultimap;
+ stdmmapcopy = stdmultimap;
+
+ if(!CheckEqualContainers(boostmapcopy, stdmapcopy))
+ return 1;
+ if(!CheckEqualContainers(boostmmapcopy, stdmmapcopy))
+ return 1;
+ }
+
+ return 0;
+}
+
+template<class MyBoostMap
+ ,class MyStdMap
+ ,class MyBoostMultiMap
+ ,class MyStdMultiMap>
+int map_test_range()
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdValueType;
+ typedef typename MyStdMap::key_type StdKeyType;
+ typedef typename MyStdMap::mapped_type StdMappedType;
+
+ //Test construction from a range
+ {
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ StdValueType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+ }
+
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
+ ( boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::key_compare());
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+ if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
+
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
+ ( boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::key_compare());
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+ if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
+ }
+ {
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ StdValueType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+ }
+
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
+ ( boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+ if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
+
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
+ ( boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+ if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
+ }
+ return 0;
+}
+
+
+template<class MyBoostMap
+ ,class MyStdMap
+ ,class MyBoostMultiMap
+ ,class MyStdMultiMap>
+int map_test_step(MyBoostMap &, MyStdMap &, MyBoostMultiMap &, MyStdMultiMap &)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+
+ {
+ //This is really nasty, but we have no other simple choice
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ typedef typename MyStdMap::value_type StdValueType;
+ typedef typename MyStdMap::key_type StdKeyType;
+ typedef typename MyStdMap::mapped_type StdMappedType;
+ StdValueType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+ }
+
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i/2);
+ IntType i2(i/2);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>
+ ( boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap2 = ::boost::movelib::make_unique<MyStdMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>
+ ( boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap2 = ::boost::movelib::make_unique<MyStdMultiMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+ MyBoostMap &boostmap2 = *pboostmap2;
+ MyStdMap &stdmap2 = *pstdmap2;
+ MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
+ MyStdMultiMap &stdmultimap2 = *pstdmultimap2;
+
+ if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+ if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1;
+
+
+
+ //ordered range insertion
+ //This is really nasty, but we have no other simple choice
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+ if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1;
+
+ //some comparison operators
+ if(!(boostmap2 == boostmap2))
+ return 1;
+ if(boostmap2 != boostmap2)
+ return 1;
+ if(boostmap2 < boostmap2)
+ return 1;
+ if(boostmap2 > boostmap2)
+ return 1;
+ if(!(boostmap2 <= boostmap2))
+ return 1;
+ if(!(boostmap2 >= boostmap2))
+ return 1;
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap3 = ::boost::movelib::make_unique<MyBoostMap>
+ ( boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap3 = ::boost::movelib::make_unique<MyStdMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap3 = ::boost::movelib::make_unique<MyBoostMultiMap>
+ ( boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap3 = ::boost::movelib::make_unique<MyStdMultiMap>
+ (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+ MyBoostMap &boostmap3 = *pboostmap3;
+ MyStdMap &stdmap3 = *pstdmap3;
+ MyBoostMultiMap &boostmultimap3 = *pboostmultimap3;
+ MyStdMultiMap &stdmultimap3 = *pstdmultimap3;
+
+ if(!CheckEqualContainers(boostmap3, stdmap3)){
+ std::cout << "Error in construct<MyBoostMap>(MyBoostMap3)" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultimap3, stdmultimap3)){
+ std::cout << "Error in construct<MyBoostMultiMap>(MyBoostMultiMap3)" << std::endl;
+ return 1;
+ }
+
+ {
+ IntType i0(0);
+ boostmap2.erase(i0);
+ boostmultimap2.erase(i0);
+ stdmap2.erase(0);
+ stdmultimap2.erase(0);
+ }
+ {
+ IntType i0(0);
+ IntType i1(1);
+ boostmap2[::boost::move(i0)] = ::boost::move(i1);
+ }
+ {
+ IntType i1(1);
+ boostmap2[IntType(0)] = ::boost::move(i1);
+ }
+ stdmap2[0] = 1;
+ if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+ }
+ return 0;
+}
+
+template<class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_insert(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdPairType;
+
+ {
+ //This is really nasty, but we have no other simple choice
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ boostmap.insert(boost::move(aux_vect[i]));
+ stdmap.insert(StdPairType(i, i));
+ boostmultimap.insert(boost::move(aux_vect3[i]));
+ stdmultimap.insert(StdPairType(i, i));
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ typename MyBoostMap::iterator it = boostmap.begin();
+ typename MyBoostMap::const_iterator cit = it;
+ (void)cit;
+
+ boostmap.erase(boostmap.begin());
+ stdmap.erase(stdmap.begin());
+ boostmultimap.erase(boostmultimap.begin());
+ stdmultimap.erase(stdmultimap.begin());
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ boostmap.erase(boostmap.begin());
+ stdmap.erase(stdmap.begin());
+ boostmultimap.erase(boostmultimap.begin());
+ stdmultimap.erase(stdmultimap.begin());
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ //Swapping test
+ MyBoostMap tmpboostemap2;
+ MyStdMap tmpstdmap2;
+ MyBoostMultiMap tmpboostemultimap2;
+ MyStdMultiMap tmpstdmultimap2;
+ boostmap.swap(tmpboostemap2);
+ stdmap.swap(tmpstdmap2);
+ boostmultimap.swap(tmpboostemultimap2);
+ stdmultimap.swap(tmpstdmultimap2);
+ boostmap.swap(tmpboostemap2);
+ stdmap.swap(tmpstdmap2);
+ boostmultimap.swap(tmpboostemultimap2);
+ stdmultimap.swap(tmpstdmultimap2);
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ return 0;
+}
+
+template<class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_erase(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdPairType;
+
+ //Insertion from other container
+ //Initialize values
+ {
+ //This is really nasty, but we have no other simple choice
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostmultimap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ for(int i = 0; i != MaxElem; ++i){
+ StdPairType stdpairtype(-1, -1);
+ stdmap.insert(stdpairtype);
+ stdmultimap.insert(stdpairtype);
+ }
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ for(int i = 0, j = static_cast<int>(boostmap.size()); i < j; ++i){
+ IntType k(i);
+ boostmap.erase(k);
+ stdmap.erase(i);
+ boostmultimap.erase(k);
+ stdmultimap.erase(i);
+ }
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ {
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect4[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect5[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(-1);
+ IntType i2(-1);
+ new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostmap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ boostmultimap.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + MaxElem));
+ boostmultimap.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + MaxElem));
+
+ for(int i = 0; i != MaxElem; ++i){
+ StdPairType stdpairtype(-1, -1);
+ stdmap.insert(stdpairtype);
+ stdmultimap.insert(stdpairtype);
+ stdmap.insert(stdpairtype);
+ stdmultimap.insert(stdpairtype);
+ }
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ boostmap.erase(boostmap.begin()->first);
+ stdmap.erase(stdmap.begin()->first);
+ boostmultimap.erase(boostmultimap.begin()->first);
+ stdmultimap.erase(stdmultimap.begin()->first);
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ return 0;
+}
+
+template<class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_insert2(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdPairType;
+
+ //This is really nasty, but we have no other simple choice
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ boostmap.insert(boost::move(aux_vect[i]));
+ stdmap.insert(StdPairType(i, i));
+ boostmultimap.insert(boost::move(aux_vect3[i]));
+ stdmultimap.insert(StdPairType(i, i));
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ IntPairType intpair;
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmap.insert(boostmap.begin(), boost::move(intpair));
+ stdmap.insert(stdmap.begin(), StdPairType(i, i));
+ //PrintContainers(boostmap, stdmap);
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmultimap.insert(boostmultimap.begin(), boost::move(intpair));
+ stdmultimap.insert(stdmultimap.begin(), StdPairType(i, i));
+ //PrintContainers(boostmultimap, stdmultimap);
+ if(!CheckEqualPairContainers(boostmap, stdmap))
+ return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+ return 1;
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmap.insert(boostmap.end(), boost::move(intpair));
+ stdmap.insert(stdmap.end(), StdPairType(i, i));
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmultimap.insert(boostmultimap.end(), boost::move(intpair));
+ stdmultimap.insert(stdmultimap.end(), StdPairType(i, i));
+ if(!CheckEqualPairContainers(boostmap, stdmap))
+ return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+ return 1;
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntType k(i);
+ boostmap.insert(boostmap.lower_bound(k), boost::move(intpair));
+ stdmap.insert(stdmap.lower_bound(i), StdPairType(i, i));
+ //PrintContainers(boostmap, stdmap);
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ {
+ IntType i1(i);
+ boostmultimap.insert(boostmultimap.lower_bound(boost::move(i1)), boost::move(intpair));
+ stdmultimap.insert(stdmultimap.lower_bound(i), StdPairType(i, i));
+ }
+
+ //PrintContainers(boostmultimap, stdmultimap);
+ if(!CheckEqualPairContainers(boostmap, stdmap))
+ return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+ return 1;
+ { //Check equal_range
+ std::pair<typename MyBoostMultiMap::iterator, typename MyBoostMultiMap::iterator> bret =
+ boostmultimap.equal_range(boostmultimap.begin()->first);
+
+ std::pair<typename MyStdMultiMap::iterator, typename MyStdMultiMap::iterator> sret =
+ stdmultimap.equal_range(stdmultimap.begin()->first);
+
+ if( boost::container::iterator_distance(bret.first, bret.second) !=
+ boost::container::iterator_distance(sret.first, sret.second) ){
+ return 1;
+ }
+ }
+ {
+ IntType i1(i);
+ boostmap.insert(boostmap.upper_bound(boost::move(i1)), boost::move(intpair));
+ stdmap.insert(stdmap.upper_bound(i), StdPairType(i, i));
+ }
+ //PrintContainers(boostmap, stdmap);
+ {
+ IntType i1(i);
+ IntType i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ {
+ IntType i1(i);
+ boostmultimap.insert(boostmultimap.upper_bound(boost::move(i1)), boost::move(intpair));
+ stdmultimap.insert(stdmultimap.upper_bound(i), StdPairType(i, i));
+ }
+ //PrintContainers(boostmultimap, stdmultimap);
+ if(!CheckEqualPairContainers(boostmap, stdmap))
+ return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+ return 1;
+
+ map_test_rebalanceable(boostmap
+ , dtl::bool_<has_member_rebalance<MyBoostMap>::value>());
+ if(!CheckEqualContainers(boostmap, stdmap)){
+ std::cout << "Error in boostmap.rebalance()" << std::endl;
+ return 1;
+ }
+ map_test_rebalanceable(boostmultimap
+ , dtl::bool_<has_member_rebalance<MyBoostMap>::value>());
+ if(!CheckEqualContainers(boostmultimap, stdmultimap)){
+ std::cout << "Error in boostmultimap.rebalance()" << std::endl;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+template<class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_search(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+
+ //Compare count/contains with std containers
+ for(int i = 0; i < MaxElem; ++i){
+ IntType k(i);
+ if(boostmap.count(k) != stdmap.count(i)){
+ return -1;
+ }
+
+ if(boostmap.contains(k) != (stdmap.find(i) != stdmap.end())){
+ return -1;
+ }
+
+ if(boostmultimap.count(k) != stdmultimap.count(i)){
+ return -1;
+ }
+
+ if(boostmultimap.contains(k) != (stdmultimap.find(i) != stdmultimap.end())){
+ return -1;
+ }
+ }
+
+ {
+ //Now do count exercise
+ boostmap.erase(boostmap.begin(), boostmap.end());
+ boostmultimap.erase(boostmultimap.begin(), boostmultimap.end());
+ boostmap.clear();
+ boostmultimap.clear();
+
+ for(int j = 0; j < 3; ++j)
+ for(int i = 0; i < 100; ++i){
+ IntPairType intpair;
+ {
+ IntType i1(i), i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmap.insert(boost::move(intpair));
+ {
+ IntType i1(i), i2(i);
+ new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmultimap.insert(boost::move(intpair));
+ IntType k(i);
+ if(boostmap.count(k) != typename MyBoostMultiMap::size_type(1))
+ return 1;
+ if(boostmultimap.count(k) != typename MyBoostMultiMap::size_type(j+1))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+template<class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+
+ { //operator[] test
+ boostmap.clear();
+ boostmultimap.clear();
+ stdmap.clear();
+ stdmultimap.clear();
+
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second);
+ stdmap[i] = i;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ return 0;
+}
+
+template< class MyBoostMap, class StdMap, class MaybeMove>
+int map_test_insert_or_assign_impl()
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyBoostMap::iterator Biterator;
+ typedef std::pair<Biterator, bool> Bpair;
+
+ MaybeMove maybe_move;
+
+ { //insert_or_assign test
+ MyBoostMap boostmap;
+ StdMap stdmap;
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(MaxElem-i);
+ new(&aux_vect[i])IntPairType(maybe_move(i1), maybe_move(i2));
+ }
+
+ IntPairType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect2[i])IntPairType(maybe_move(i1), maybe_move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ Bpair r = boostmap.insert_or_assign(maybe_move(aux_vect[i].first), maybe_move(aux_vect[i].second));
+ stdmap[i] = MaxElem-i;
+ if(!r.second)
+ return 1;
+ const IntType key(i);
+ if(r.first->first != key)
+ return 1;
+ const IntType mapped(MaxElem-i);
+ if(r.first->second != mapped)
+ return 1;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ Bpair r = boostmap.insert_or_assign(maybe_move(aux_vect2[i].first), maybe_move(aux_vect2[i].second));
+ stdmap[i] = i;
+ if(r.second)
+ return 1;
+ const IntType key(i);
+ if(r.first->first != key)
+ return 1;
+ const IntType mapped(i);
+ if(r.first->second != mapped)
+ return 1;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ }
+ { //insert_or_assign test with hint
+ MyBoostMap boostmap;
+ StdMap stdmap;
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(MaxElem-i);
+ new(&aux_vect[i])IntPairType(maybe_move(i1), maybe_move(i2));
+ }
+
+ IntPairType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect2[i])IntPairType(maybe_move(i1), maybe_move(i2));
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ Biterator r = boostmap.insert_or_assign(boostmap.end(), maybe_move(aux_vect[i].first), maybe_move(aux_vect[i].second));
+ stdmap[i] = MaxElem-i;
+ const IntType key(i);
+ if(r->first != key)
+ return 1;
+ const IntType mapped(MaxElem-i);
+ if(r->second != mapped)
+ return 1;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ Biterator r = boostmap.insert_or_assign(boostmap.end(), maybe_move(aux_vect2[i].first), maybe_move(aux_vect2[i].second));
+ stdmap[i] = i;
+ const IntType key(i);
+ if(r->first != key)
+ return 1;
+ const IntType mapped(i);
+ if(r->second != mapped)
+ return 1;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ }
+ return 0;
+}
+
+template< class MyBoostMap, class StdMap>
+int map_test_insert_or_assign(dtl::bool_<false> )//noncopyable
+{
+ return map_test_insert_or_assign_impl<MyBoostMap, StdMap, move_op>();
+}
+
+template< class MyBoostMap, class StdMap>
+int map_test_insert_or_assign(dtl::bool_<true> )//copyable
+{
+ int r = map_test_insert_or_assign_impl<MyBoostMap, StdMap, const_ref_op>();
+ if (r)
+ r = map_test_insert_or_assign_impl<MyBoostMap, StdMap, move_op>();
+ return r;
+}
+
+template< class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_try_emplace(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+
+ { //try_emplace
+ boostmap.clear();
+ boostmultimap.clear();
+ stdmap.clear();
+ stdmultimap.clear();
+
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(MaxElem-i);
+ new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ typedef typename MyBoostMap::iterator iterator;
+ for(int i = 0; i < MaxElem; ++i){
+ iterator it;
+ if(i&1){
+ std::pair<typename MyBoostMap::iterator, bool> ret =
+ boostmap.try_emplace(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
+ if(!ret.second)
+ return 1;
+ it = ret.first;
+ }
+ else{
+ it = boostmap.try_emplace
+ (boostmap.upper_bound(aux_vect[i].first), boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
+ }
+ if(boostmap.end() == it || it->first != aux_vect2[i].first || it->second != aux_vect2[i].first){
+ return 1;
+ }
+ stdmap[i] = i;
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ iterator it;
+ iterator itex = boostmap.find(aux_vect2[i].first);
+ if(itex == boostmap.end())
+ return 1;
+ if(i&1){
+ std::pair<typename MyBoostMap::iterator, bool> ret =
+ boostmap.try_emplace(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
+ if(ret.second)
+ return 1;
+ it = ret.first;
+ }
+ else{
+ it = boostmap.try_emplace
+ (boostmap.upper_bound(aux_vect2[i].first), boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
+ }
+ const IntType test_int(i);
+ if(boostmap.end() == it || it != itex || it->second != test_int){
+ return 1;
+ }
+ }
+
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ return 0;
+}
+
+
+template< class MyBoostMap
+ , class MyStdMap
+ , class MyBoostMultiMap
+ , class MyStdMultiMap>
+int map_test_merge(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap)
+{
+ typedef typename MyBoostMap::key_type IntType;
+ typedef dtl::pair<IntType, IntType> IntPairType;
+ typedef typename MyStdMap::value_type StdPairType;
+
+ { //merge
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>();
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>();
+
+ MyBoostMap &boostmap2 = *pboostmap2;
+ MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
+
+ boostmap.clear();
+ boostmap2.clear();
+ boostmultimap.clear();
+ boostmultimap2.clear();
+ stdmap.clear();
+ stdmultimap.clear();
+
+ {
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(MaxElem/2+i);
+ IntType i2(MaxElem-i);
+ new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(MaxElem*2/2+i);
+ IntType i2(MaxElem*2+i);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostmap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+ boostmultimap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmap.insert(StdPairType(i, i));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
+ }
+
+ boostmap.merge(boost::move(boostmap2));
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ stdmap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
+ }
+
+ boostmap.merge(boost::move(boostmultimap2));
+ if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+ boostmap.clear();
+ boostmap2.clear();
+ boostmultimap.clear();
+ boostmultimap2.clear();
+ stdmap.clear();
+ stdmultimap.clear();
+ {
+ IntPairType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(i);
+ IntType i2(i);
+ new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+
+ IntPairType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(MaxElem/2+i);
+ IntType i2(MaxElem-i);
+ new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ IntPairType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ IntType i1(MaxElem*2/2+i);
+ IntType i2(MaxElem*2+i);
+ new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+ }
+ boostmultimap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostmultimap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+ boostmap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultimap.insert(StdPairType(i, i));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultimap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
+ }
+ boostmultimap.merge(boostmultimap2);
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultimap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
+ }
+
+ boostmultimap.merge(boostmap2);
+ if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+ }
+ return 0;
+}
+
+
+template<class MyBoostMap
+ ,class MyStdMap
+ ,class MyBoostMultiMap
+ ,class MyStdMultiMap>
+int map_test()
+{
+ typedef typename MyBoostMap::key_type IntType;
+
+ if(map_test_range<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>())
+ return 1;
+
+ ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
+ ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>();
+ ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>();
+ ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>();
+ MyBoostMap &boostmap = *pboostmap;
+ MyStdMap &stdmap = *pstdmap;
+ MyBoostMultiMap &boostmultimap = *pboostmultimap;
+ MyStdMultiMap &stdmultimap = *pstdmultimap;
+ typedef dtl::bool_<boost::container::test::is_copyable<IntType>::value> copyable_t;
+
+ if (map_test_step(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_insert(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_erase(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_insert2(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_search(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_indexing(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_try_emplace(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_merge(boostmap, stdmap, boostmultimap, stdmultimap))
+ return 1;
+
+ if (map_test_insert_or_assign<MyBoostMap, MyStdMap>(copyable_t()))
+ return 1;
+
+ if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>(copyable_t()))
+ return 1;
+ return 0;
+}
+
+template<typename MapType>
+bool test_map_support_for_initialization_list_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ const std::initializer_list<std::pair<typename MapType::value_type::first_type, typename MapType::mapped_type>> il
+ = { std::make_pair(1, 2), std::make_pair(3, 4) };
+
+ const MapType expected_map(il.begin(), il.end());
+ {
+ const MapType sil = il;
+ if (sil != expected_map)
+ return false;
+
+ MapType sila(il, typename MapType::allocator_type());
+ if (sila != expected_map)
+ return false;
+
+ MapType silca(il, typename MapType::key_compare(), typename MapType::allocator_type());
+ if (silca != expected_map)
+ return false;
+
+ const MapType sil_ordered(ordered_unique_range, il);
+ if (sil_ordered != expected_map)
+ return false;
+
+ MapType sil_assign = { std::make_pair(99, 100) };
+ sil_assign = il;
+ if (sil_assign != expected_map)
+ return false;
+ }
+ {
+ MapType sil;
+ sil.insert(il);
+ if (sil != expected_map)
+ return false;
+ }
+ return true;
+#endif
+ return true;
+}
+
+template<typename MapType, typename MultimapType>
+bool instantiate_constructors()
+{
+ {
+ typedef typename MapType::value_type value_type;
+ typename MapType::key_compare comp;
+ typename MapType::allocator_type a;
+ value_type value;
+ {
+ MapType s0;
+ MapType s1(comp);
+ MapType s2(a);
+ MapType s3(comp, a);
+ }
+ {
+ MapType s0(&value, &value);
+ MapType s1(&value, &value ,comp);
+ MapType s2(&value, &value ,a);
+ MapType s3(&value, &value ,comp, a);
+ }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ {
+ std::initializer_list<value_type> il;
+ MapType s0(il);
+ MapType s1(il, comp);
+ MapType s2(il, a);
+ MapType s3(il, comp, a);
+ }
+ {
+ std::initializer_list<value_type> il;
+ MapType s0(ordered_unique_range, il);
+ MapType s1(ordered_unique_range, il, comp);
+ MapType s3(ordered_unique_range, il, comp, a);
+ }
+ #endif
+ {
+ MapType s0(ordered_unique_range, &value, &value);
+ MapType s1(ordered_unique_range, &value, &value ,comp);
+ MapType s2(ordered_unique_range, &value, &value ,comp, a);
+ }
+ }
+
+ {
+ typedef typename MultimapType::value_type value_type;
+ typename MultimapType::key_compare comp;
+ typename MultimapType::allocator_type a;
+ value_type value;
+ {
+ MultimapType s0;
+ MultimapType s1(comp);
+ MultimapType s2(a);
+ MultimapType s3(comp, a);
+ }
+ {
+ MultimapType s0(&value, &value);
+ MultimapType s1(&value, &value ,comp);
+ MultimapType s2(&value, &value ,a);
+ MultimapType s3(&value, &value ,comp, a);
+ }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ {
+ std::initializer_list<value_type> il;
+ MultimapType s0(il);
+ MultimapType s1(il, comp);
+ MultimapType s2(il, a);
+ MultimapType s3(il, comp, a);
+ }
+ {
+ std::initializer_list<value_type> il;
+ MultimapType s0(ordered_range, il);
+ MultimapType s1(ordered_range, il, comp);
+ MultimapType s3(ordered_range, il, comp, a);
+ }
+ #endif
+ {
+ MultimapType s0(ordered_range, &value, &value);
+ MultimapType s1(ordered_range, &value, &value ,comp);
+ MultimapType s2(ordered_range, &value, &value ,comp, a);
+ }
+ }
+ return true;
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER
diff --git a/src/boost/libs/container/test/memory_resource_logger.hpp b/src/boost/libs/container/test/memory_resource_logger.hpp
new file mode 100644
index 000000000..e8bc405b8
--- /dev/null
+++ b/src/boost/libs/container/test/memory_resource_logger.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
+#define BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
+
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/vector.hpp>
+#include <cstdlib>
+
+class memory_resource_logger
+ : public boost::container::pmr::memory_resource
+{
+ public:
+ struct allocation_info
+ {
+ char *address;
+ std::size_t bytes;
+ std::size_t alignment;
+ };
+
+ boost::container::vector<allocation_info> m_info;
+ unsigned m_mismatches;
+
+ explicit memory_resource_logger()
+ : m_info()
+ , m_mismatches()
+ {}
+
+ virtual ~memory_resource_logger()
+ { this->reset(); }
+
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+ {
+ char *addr =(char*)std::malloc(bytes);
+ if(!addr){
+ throw std::bad_alloc();
+ }
+ allocation_info info;
+ info.address = addr;
+ info.bytes = bytes;
+ info.alignment = alignment;
+ m_info.push_back(info);
+ return addr;
+ }
+
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+ {
+ std::size_t i = 0, max = m_info.size();
+ while(i != max && m_info[i].address != p){
+ ++i;
+ }
+ if(i == max){
+ ++m_mismatches;
+ }
+ else{
+ const allocation_info &info = m_info[i];
+ m_mismatches += info.bytes != bytes || info.alignment != alignment;
+ std::free(p);
+ m_info.erase(m_info.nth(i));
+ }
+ }
+
+ virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
+ {
+ return static_cast<const memory_resource *>(this) == &other;
+ }
+
+ void reset()
+ {
+ while(!m_info.empty()){
+ std::free(m_info.back().address);
+ m_info.pop_back();
+ }
+ m_mismatches = 0u;
+ }
+};
+
+#endif //#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
diff --git a/src/boost/libs/container/test/memory_resource_test.cpp b/src/boost/libs/container/test/memory_resource_test.cpp
new file mode 100644
index 000000000..4c4cb511b
--- /dev/null
+++ b/src/boost/libs/container/test/memory_resource_test.cpp
@@ -0,0 +1,135 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include "derived_from_memory_resource.hpp"
+
+#include <cstdlib>
+
+using namespace boost::container;
+using namespace boost::container::pmr;
+
+void test_allocate()
+{
+ derived_from_memory_resource d;
+ memory_resource &mr = d;
+
+ d.reset();
+ BOOST_TEST(d.do_allocate_called == false);
+ BOOST_TEST(d.do_allocate_bytes == 0);
+ BOOST_TEST(d.do_allocate_alignment == 0);
+
+ mr.allocate(2, 4);
+ BOOST_TEST(d.do_allocate_called == true);
+ BOOST_TEST(d.do_allocate_bytes == 2);
+ BOOST_TEST(d.do_allocate_alignment == 4);
+}
+
+void test_deallocate()
+{
+ derived_from_memory_resource d;
+ memory_resource &mr = d;
+
+ d.reset();
+ BOOST_TEST(d.do_deallocate_called == false);
+ BOOST_TEST(d.do_deallocate_p == 0);
+ BOOST_TEST(d.do_allocate_bytes == 0);
+ BOOST_TEST(d.do_allocate_alignment == 0);
+
+ mr.deallocate(&d, 2, 4);
+ BOOST_TEST(d.do_deallocate_called == true);
+ BOOST_TEST(d.do_deallocate_p == &d);
+ BOOST_TEST(d.do_deallocate_bytes == 2);
+ BOOST_TEST(d.do_deallocate_alignment == 4);
+}
+
+void test_destructor()
+{
+ {
+ derived_from_memory_resource d;
+ d.reset();
+ BOOST_TEST(derived_from_memory_resource::destructor_called == false);
+ }
+ BOOST_TEST(derived_from_memory_resource::destructor_called == true);
+}
+
+void test_is_equal()
+{
+ derived_from_memory_resource d;
+ memory_resource &mr = d;
+
+ d.reset();
+ BOOST_TEST(d.do_is_equal_called == false);
+ BOOST_TEST(d.do_is_equal_other == 0);
+
+ mr.is_equal(d);
+ BOOST_TEST(d.do_is_equal_called == true);
+ BOOST_TEST(d.do_is_equal_other == &d);
+}
+
+void test_equality_operator()
+{
+ derived_from_memory_resource d;
+ memory_resource &mr = d;
+
+ d.reset();
+ BOOST_TEST(d.do_is_equal_called == false);
+ BOOST_TEST(d.do_is_equal_other == 0);
+
+ //equal addresses are shorcircuited
+ BOOST_TEST((mr == mr) == true);
+ BOOST_TEST(d.do_is_equal_called == false);
+ BOOST_TEST(d.do_is_equal_other == 0);
+
+ //unequal addresses are dispatched to is_equal which in turn calls do_is_equal
+ derived_from_memory_resource d2(1);
+ d.reset();
+ d2.reset();
+ memory_resource &mr2 = d2;
+ BOOST_TEST((mr == mr2) == false);
+ BOOST_TEST(d.do_is_equal_called == true);
+ BOOST_TEST(d.do_is_equal_other == &d2);
+}
+
+void test_inequality_operator()
+{
+ derived_from_memory_resource d;
+ memory_resource &mr = d;
+
+ d.reset();
+ BOOST_TEST(d.do_is_equal_called == false);
+ BOOST_TEST(d.do_is_equal_other == 0);
+
+ //equal addresses are shorcircuited
+ BOOST_TEST((mr != mr) == false);
+ BOOST_TEST(d.do_is_equal_called == false);
+ BOOST_TEST(d.do_is_equal_other == 0);
+
+ //unequal addresses are dispatched to is_equal which in turn calls do_is_equal
+ derived_from_memory_resource d2(1);
+ d.reset();
+ d2.reset();
+ memory_resource &mr2 = d2;
+ BOOST_TEST((mr != mr2) == true);
+ BOOST_TEST(d.do_is_equal_called == true);
+ BOOST_TEST(d.do_is_equal_other == &d2);
+}
+
+int main()
+{
+ test_destructor();
+ test_allocate();
+ test_deallocate();
+ test_is_equal();
+ test_equality_operator();
+ test_inequality_operator();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp b/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp
new file mode 100644
index 000000000..4923e2460
--- /dev/null
+++ b/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp
@@ -0,0 +1,483 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/monotonic_buffer_resource.hpp>
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "derived_from_memory_resource.hpp"
+#include "memory_resource_logger.hpp"
+
+using namespace boost::container::pmr;
+
+static const std::size_t AllocCount = 32u;
+
+namespace test_block_chain{
+
+//explicit block_slist(memory_resource &upstream_rsrc)
+void test_constructor()
+{
+ memory_resource_logger mrl;
+ block_slist bc(mrl);
+ //Resource stored
+ BOOST_TEST(&bc.upstream_resource() == &mrl);
+ //No allocation performed
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+//void *allocate(std::size_t size)
+void test_allocate()
+{
+ memory_resource_logger mrl;
+ block_slist bc(mrl);
+
+ for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+ //Allocate and trace data
+ const std::size_t alloc = i+1;
+ char *const addr = (char*)bc.allocate(alloc);
+ //Should have allocated a new entry
+ BOOST_TEST(mrl.m_info.size() == (i+1));
+ //Requested size must be bigger to include metadata
+ BOOST_TEST(mrl.m_info[i].bytes > alloc);
+ BOOST_TEST(mrl.m_info[i].alignment == memory_resource::max_align);
+ //Returned address should be between the allocated buffer
+ BOOST_TEST(mrl.m_info[i].address < addr);
+ BOOST_TEST(addr < (mrl.m_info[i].address + mrl.m_info[i].bytes));
+ //Allocate size should include all requested size
+ BOOST_TEST((addr + alloc) <= (mrl.m_info[i].address + mrl.m_info[i].bytes));
+ //Allocation must be max-aligned
+ BOOST_TEST((std::size_t(addr) % memory_resource::max_align) == 0);
+ }
+}
+
+//void release() BOOST_NOEXCEPT
+void test_release()
+{
+ memory_resource_logger mrl;
+ block_slist bc(mrl);
+
+ //Allocate and trace data
+ char *bufs[AllocCount];
+ for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+ bufs[i] = (char*)bc.allocate(i+1);
+ }
+ (void)bufs;
+ //Should have allocated a new entry
+ BOOST_TEST(mrl.m_info.size() == AllocCount);
+
+ //Now release and check all allocations match deallocations
+ bc.release();
+ BOOST_TEST(mrl.m_mismatches == 0);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+//memory_resource* upstream_resource()
+void test_memory_resource()
+{
+ derived_from_memory_resource d;
+ block_slist bc(d);
+ //Resource stored
+ BOOST_TEST(&bc.upstream_resource() == &d);
+}
+
+//~block_slist() { this->release(); }
+void test_destructor()
+{
+ memory_resource_logger mrl;
+ {
+ block_slist bc(mrl);
+
+ //Allocate and trace data
+ char *bufs[AllocCount];
+ for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+ bufs[i] = (char*)bc.allocate(i+1);
+ }
+ (void)bufs;
+ //Should have allocated a new entry
+ BOOST_TEST(mrl.m_info.size() == AllocCount);
+
+ //Destructor should release all memory
+ }
+ BOOST_TEST(mrl.m_mismatches == 0);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+} //namespace test_block_chain {
+
+void test_resource_constructor()
+{
+ //First constructor, null resource
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ monotonic_buffer_resource m;
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(0);
+ }
+ //First constructor, non-null resource
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ monotonic_buffer_resource m(&dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
+ BOOST_TEST(m.current_buffer() == 0);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+void test_initial_size_constructor()
+{
+ //Second constructor, null resource
+ const std::size_t initial_size = monotonic_buffer_resource::initial_next_buffer_size*2;
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ monotonic_buffer_resource m(initial_size);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.next_buffer_size() >= initial_size);
+ BOOST_TEST(m.current_buffer() == 0);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(0);
+ }
+ //Second constructor, non-null resource
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ monotonic_buffer_resource m(initial_size, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.next_buffer_size() >= initial_size);
+ BOOST_TEST(m.current_buffer() == 0);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+void test_buffer_constructor()
+{
+ const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size*2;
+ unsigned char buf[BufSz];
+ //Third constructor, null resource
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ monotonic_buffer_resource m(buf, BufSz);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.next_buffer_size() >= BufSz*2);
+ BOOST_TEST(m.current_buffer() == buf);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(0);
+ }
+ //Third constructor, non-null resource
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ monotonic_buffer_resource m(buf, sizeof(buf), &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.next_buffer_size() >= sizeof(buf)*2);
+ BOOST_TEST(m.current_buffer() == buf);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+ //Check for empty buffers
+ {
+ monotonic_buffer_resource m(buf, 0);
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.next_buffer_size() > 1);
+ BOOST_TEST(m.current_buffer() == buf);
+ }
+}
+
+struct derived_from_monotonic_buffer_resource
+ : public monotonic_buffer_resource
+{
+ explicit derived_from_monotonic_buffer_resource(memory_resource *p)
+ : monotonic_buffer_resource(p)
+ {}
+
+ explicit derived_from_monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream)
+ : monotonic_buffer_resource(initial_size, upstream)
+ {}
+
+ explicit derived_from_monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream)
+ : monotonic_buffer_resource(buffer, buffer_size, upstream)
+ {}
+
+ using monotonic_buffer_resource::do_allocate;
+ using monotonic_buffer_resource::do_deallocate;
+ using monotonic_buffer_resource::do_is_equal;
+};
+
+void test_upstream_resource()
+{
+ //Allocate buffer first to avoid stack-use-after-scope in monotonic_buffer_resource's destructor
+ const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size;
+ boost::move_detail::aligned_storage<BufSz+block_slist::header_size>::type buf;
+ //Test stores the resource and uses it to allocate memory
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ derived_from_monotonic_buffer_resource dmbr(&dmr);
+ //Resource must be stored and initial values given (no current buffer)
+ BOOST_TEST(dmbr.upstream_resource() == &dmr);
+ BOOST_TEST(dmbr.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
+ BOOST_TEST(dmbr.current_buffer() == 0);
+ //Test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ //Now stub buffer storage it as the return buffer
+ //for "derived_from_memory_resource":
+ dmr.do_allocate_return = &buf;
+ //Test that allocation uses the upstream_resource()
+ void *addr = dmbr.do_allocate(1u, 1u);
+ //Test returns stubbed memory with the internal initial size plus metadata size
+ BOOST_TEST(addr > (char*)&buf);
+ BOOST_TEST(addr < (char*)(&buf+1));
+ BOOST_TEST(dmr.do_allocate_called == true);
+ BOOST_TEST(dmr.do_allocate_bytes > BufSz);
+ //Alignment for the resource must be max_align
+ BOOST_TEST(dmr.do_allocate_alignment == memory_resource::max_align);
+}
+
+void test_do_allocate()
+{
+ memory_resource_logger mrl;
+ {
+ std::size_t remaining_storage = 0u;
+ derived_from_monotonic_buffer_resource dmbr(&mrl);
+ //First test, no buffer
+ {
+ dmbr.do_allocate(1, 1);
+ //It should allocate initial size
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ //... which requests the initial size plus the header size to the allcoator
+ BOOST_TEST(mrl.m_info[0].bytes == monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+ std::size_t remaining = dmbr.remaining_storage(1u);
+ //Remaining storage should be one less than initial, as we requested 1 byte with minimal alignment
+ BOOST_TEST(remaining == monotonic_buffer_resource::initial_next_buffer_size-1u);
+ remaining_storage = remaining;
+ }
+ //Now ask for more internal storage with misaligned current buffer
+ {
+ //Test wasted space
+ std::size_t wasted_due_to_alignment;
+ dmbr.remaining_storage(4u, wasted_due_to_alignment);
+ BOOST_TEST(wasted_due_to_alignment == 3u);
+ dmbr.do_allocate(4, 4);
+ //It should not have allocated
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ std::size_t remaining = dmbr.remaining_storage(1u);
+ //We wasted some bytes due to alignment plus 4 bytes of real storage
+ BOOST_TEST(remaining == remaining_storage - 4 - wasted_due_to_alignment);
+ remaining_storage = remaining;
+ }
+ //Now request the same alignment to test no storage is wasted
+ {
+ std::size_t wasted_due_to_alignment;
+ std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ dmbr.do_allocate(4, 4);
+ //It should not have allocated
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ remaining = dmbr.remaining_storage(1u);
+ //We wasted no bytes due to alignment plus 4 bytes of real storage
+ BOOST_TEST(remaining == remaining_storage - 4u);
+ remaining_storage = remaining;
+ }
+ //Now exhaust the remaining storage with 2 byte alignment (the last allocation
+ //was 4 bytes with 4 byte alignment) so it should be already 2-byte aligned.
+ {
+ dmbr.do_allocate(remaining_storage, 2);
+ std::size_t wasted_due_to_alignment;
+ std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
+ BOOST_TEST(wasted_due_to_alignment == 0u);
+ BOOST_TEST(remaining == 0u);
+ //It should not have allocated
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ remaining_storage = 0u;
+ }
+ //The next allocation should trigger the upstream resource, even with a 1 byte
+ //allocation.
+ {
+ dmbr.do_allocate(1u, 1u);
+ BOOST_TEST(mrl.m_info.size() == 2u);
+ //The next allocation should be geometrically bigger.
+ BOOST_TEST(mrl.m_info[1].bytes == 2*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+ std::size_t wasted_due_to_alignment;
+ //For a 2 byte alignment one byte will be wasted from the previous 1 byte allocation
+ std::size_t remaining = dmbr.remaining_storage(2u, wasted_due_to_alignment);
+ BOOST_TEST(wasted_due_to_alignment == 1u);
+ BOOST_TEST(remaining == (mrl.m_info[1].bytes - 1u - wasted_due_to_alignment - block_slist::header_size));
+ //It should not have allocated
+ remaining_storage = dmbr.remaining_storage(1u);
+ }
+ //Now try a bigger than next allocation and see if next_buffer_size is doubled.
+ {
+ std::size_t next_alloc = 5*monotonic_buffer_resource::initial_next_buffer_size;
+ dmbr.do_allocate(next_alloc, 1u);
+ BOOST_TEST(mrl.m_info.size() == 3u);
+ //The next allocation should be geometrically bigger.
+ BOOST_TEST(mrl.m_info[2].bytes == 8*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+ remaining_storage = dmbr.remaining_storage(1u);
+ }
+ }
+ //derived_from_monotonic_buffer_resource dmbr(&mrl) is destroyed
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+
+ //Now use a local buffer
+ {
+ boost::move_detail::aligned_storage
+ <monotonic_buffer_resource::initial_next_buffer_size>::type buf;
+ //Supply an external buffer
+ derived_from_monotonic_buffer_resource dmbr(&buf, sizeof(buf), &mrl);
+ BOOST_TEST(dmbr.remaining_storage(1u) == sizeof(buf));
+ //Allocate all remaining storage
+ dmbr.do_allocate(dmbr.remaining_storage(1u), 1u);
+ //No new allocation should have occurred
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ BOOST_TEST(dmbr.remaining_storage(1u) == 0u);
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+void test_do_deallocate()
+{
+ memory_resource_logger mrl;
+ const std::size_t initial_size = 1u;
+ {
+ derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+ //First test, no buffer
+ const unsigned iterations = 8;
+ char *bufs[iterations];
+ std::size_t sizes[iterations];
+ //Test each iteration allocates memory
+ for(unsigned i = 0; i != iterations; ++i)
+ {
+ sizes[i] = dmbr.remaining_storage()+1;
+ bufs[i] = (char*)dmbr.do_allocate(sizes[i], 1);
+ BOOST_TEST(mrl.m_info.size() == (i+1));
+ }
+ std::size_t remaining = dmbr.remaining_storage();
+ //Test do_deallocate does not release any storage
+ for(unsigned i = 0; i != iterations; ++i)
+ {
+ dmbr.do_deallocate(bufs[i], sizes[i], 1u);
+ BOOST_TEST(mrl.m_info.size() == iterations);
+ BOOST_TEST(remaining == dmbr.remaining_storage());
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ }
+ }
+}
+
+void test_do_is_equal()
+{
+ //! <b>Returns</b>:
+ //! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
+ memory_resource_logger mrl;
+ derived_from_monotonic_buffer_resource dmbr(&mrl);
+ derived_from_monotonic_buffer_resource dmbr2(&mrl);
+ BOOST_TEST(true == dmbr.do_is_equal(dmbr));
+ BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
+ //A different type should be always different
+ derived_from_memory_resource dmr;
+ BOOST_TEST(false == dmbr.do_is_equal(dmr));
+}
+
+void test_release()
+{
+ {
+ memory_resource_logger mrl;
+ const std::size_t initial_size = 1u;
+ derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+ //First test, no buffer
+ const unsigned iterations = 8;
+ //Test each iteration allocates memory
+ for(unsigned i = 0; i != iterations; ++i)
+ {
+ dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
+ BOOST_TEST(mrl.m_info.size() == (i+1));
+ }
+ //Release and check memory was released
+ dmbr.release();
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ }
+ //Now use a local buffer
+ {
+ boost::move_detail::aligned_storage
+ <monotonic_buffer_resource::initial_next_buffer_size>::type buf;
+ //Supply an external buffer
+ monotonic_buffer_resource monr(&buf, sizeof(buf));
+ memory_resource &mr = monr;
+ BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
+ //Allocate all remaining storage
+ mr.allocate(monr.remaining_storage(1u), 1u);
+ BOOST_TEST(monr.current_buffer() == ((char*)&buf + sizeof(buf)));
+ //No new allocation should have occurred
+ BOOST_TEST(monr.remaining_storage(1u) == 0u);
+ //Release and check memory was released and the original buffer is back
+ monr.release();
+ BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
+ BOOST_TEST(monr.current_buffer() == &buf);
+ }
+}
+
+void test_destructor()
+{
+ memory_resource_logger mrl;
+ const std::size_t initial_size = 1u;
+ {
+ derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+ //First test, no buffer
+ const unsigned iterations = 8;
+ //Test each iteration allocates memory
+ for(unsigned i = 0; i != iterations; ++i)
+ {
+ dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
+ BOOST_TEST(mrl.m_info.size() == (i+1));
+ }
+ } //dmbr is destroyed, memory should be released
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+int main()
+{
+ test_block_chain::test_constructor();
+ test_block_chain::test_allocate();
+ test_block_chain::test_release();
+ test_block_chain::test_memory_resource();
+ test_block_chain::test_destructor();
+
+ test_resource_constructor();
+ test_initial_size_constructor();
+ test_buffer_constructor();
+
+ test_upstream_resource();
+ test_do_allocate();
+ test_do_deallocate();
+ test_do_is_equal();
+ test_release();
+ test_destructor();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/movable_int.hpp b/src/boost/libs/container/test/movable_int.hpp
new file mode 100644
index 000000000..c38146ecf
--- /dev/null
+++ b/src/boost/libs/container/test/movable_int.hpp
@@ -0,0 +1,437 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
+#define BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
+#include <ostream>
+#include <climits>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<class T>
+struct is_copyable;
+
+template<>
+struct is_copyable<int>
+{
+ static const bool value = true;
+};
+
+
+class movable_int
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int)
+
+ public:
+
+ static unsigned int count;
+
+ movable_int()
+ : m_int(0)
+ { ++count; }
+
+ explicit movable_int(int a)
+ : m_int(a)
+ {
+ //Disallow INT_MIN
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ ++count;
+ }
+
+ movable_int(BOOST_RV_REF(movable_int) mmi)
+ : m_int(mmi.m_int)
+ { mmi.m_int = 0; ++count; }
+
+ movable_int & operator= (BOOST_RV_REF(movable_int) mmi)
+ { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; }
+
+ movable_int & operator= (int i)
+ { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; }
+
+ ~movable_int()
+ {
+ //Double destructor called
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ this->m_int = INT_MIN;
+ --count;
+ }
+
+ friend bool operator ==(const movable_int &l, const movable_int &r)
+ { return l.m_int == r.m_int; }
+
+ friend bool operator !=(const movable_int &l, const movable_int &r)
+ { return l.m_int != r.m_int; }
+
+ friend bool operator <(const movable_int &l, const movable_int &r)
+ { return l.m_int < r.m_int; }
+
+ friend bool operator <=(const movable_int &l, const movable_int &r)
+ { return l.m_int <= r.m_int; }
+
+ friend bool operator >=(const movable_int &l, const movable_int &r)
+ { return l.m_int >= r.m_int; }
+
+ friend bool operator >(const movable_int &l, const movable_int &r)
+ { return l.m_int > r.m_int; }
+
+ int get_int() const
+ { return m_int; }
+
+ friend bool operator==(const movable_int &l, int r)
+ { return l.get_int() == r; }
+
+ friend bool operator==(int l, const movable_int &r)
+ { return l == r.get_int(); }
+
+ friend bool operator<(const movable_int &l, int r)
+ { return l.get_int() < r; }
+
+ friend bool operator<(int l, const movable_int &r)
+ { return l < r.get_int(); }
+
+ friend std::size_t hash_value(const movable_int &v)
+ { return (std::size_t)v.get_int(); }
+
+ private:
+ int m_int;
+};
+
+unsigned int movable_int::count = 0;
+
+inline movable_int produce_movable_int()
+{ return movable_int(); }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+ (std::basic_ostream<E, T> & os, movable_int const & p)
+
+{
+ os << p.get_int();
+ return os;
+}
+
+template<>
+struct is_copyable<movable_int>
+{
+ static const bool value = false;
+};
+
+class movable_and_copyable_int
+{
+ BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int)
+
+ public:
+
+ static unsigned int count;
+
+ movable_and_copyable_int()
+ : m_int(0)
+ { ++count; }
+
+ explicit movable_and_copyable_int(int a)
+ : m_int(a)
+ {
+ //Disallow INT_MIN
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ ++count;
+ }
+
+ movable_and_copyable_int(const movable_and_copyable_int& mmi)
+ : m_int(mmi.m_int)
+ { ++count; }
+
+ movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi)
+ : m_int(mmi.m_int)
+ { mmi.m_int = 0; ++count; }
+
+ ~movable_and_copyable_int()
+ {
+ //Double destructor called
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ this->m_int = INT_MIN;
+ --count;
+ }
+
+ movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi)
+ { this->m_int = mi.m_int; return *this; }
+
+ movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi)
+ { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; }
+
+ movable_and_copyable_int & operator= (int i)
+ { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; }
+
+ friend bool operator ==(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int == r.m_int; }
+
+ friend bool operator !=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int != r.m_int; }
+
+ friend bool operator <(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int < r.m_int; }
+
+ friend bool operator <=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int <= r.m_int; }
+
+ friend bool operator >=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int >= r.m_int; }
+
+ friend bool operator >(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+ { return l.m_int > r.m_int; }
+
+ int get_int() const
+ { return m_int; }
+
+ friend bool operator==(const movable_and_copyable_int &l, int r)
+ { return l.get_int() == r; }
+
+ friend bool operator==(int l, const movable_and_copyable_int &r)
+ { return l == r.get_int(); }
+
+ friend bool operator<(const movable_and_copyable_int &l, int r)
+ { return l.get_int() < r; }
+
+ friend bool operator<(int l, const movable_and_copyable_int &r)
+ { return l < r.get_int(); }
+
+ friend std::size_t hash_value(const movable_and_copyable_int &v)
+ { return (std::size_t)v.get_int(); }
+
+ private:
+ int m_int;
+};
+
+unsigned int movable_and_copyable_int::count = 0;
+
+inline movable_and_copyable_int produce_movable_and_copyable_int()
+{ return movable_and_copyable_int(); }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+ (std::basic_ostream<E, T> & os, movable_and_copyable_int const & p)
+
+{
+ os << p.get_int();
+ return os;
+}
+
+template<>
+struct is_copyable<movable_and_copyable_int>
+{
+ static const bool value = true;
+};
+
+class copyable_int
+{
+ public:
+
+ static unsigned int count;
+
+ copyable_int()
+ : m_int(0)
+ { ++count; }
+
+ explicit copyable_int(int a)
+ : m_int(a)
+ {
+ //Disallow INT_MIN
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ ++count;
+ }
+
+ copyable_int(const copyable_int& mmi)
+ : m_int(mmi.m_int)
+ { ++count; }
+
+ copyable_int & operator= (int i)
+ { this->m_int = i; BOOST_ASSERT(this->m_int != INT_MIN); return *this; }
+
+ copyable_int & operator= (const copyable_int &ci)
+ { this->m_int = ci.m_int; BOOST_ASSERT(this->m_int != INT_MIN); return *this; }
+
+ ~copyable_int()
+ {
+ //Double destructor called
+ BOOST_ASSERT(this->m_int != INT_MIN);
+ this->m_int = INT_MIN;
+ --count;
+ }
+
+ friend bool operator ==(const copyable_int &l, const copyable_int &r)
+ { return l.m_int == r.m_int; }
+
+ friend bool operator !=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int != r.m_int; }
+
+ friend bool operator <(const copyable_int &l, const copyable_int &r)
+ { return l.m_int < r.m_int; }
+
+ friend bool operator <=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int <= r.m_int; }
+
+ friend bool operator >=(const copyable_int &l, const copyable_int &r)
+ { return l.m_int >= r.m_int; }
+
+ friend bool operator >(const copyable_int &l, const copyable_int &r)
+ { return l.m_int > r.m_int; }
+
+ int get_int() const
+ { return m_int; }
+
+ friend bool operator==(const copyable_int &l, int r)
+ { return l.get_int() == r; }
+
+ friend bool operator==(int l, const copyable_int &r)
+ { return l == r.get_int(); }
+
+ friend bool operator<(const copyable_int &l, int r)
+ { return l.get_int() < r; }
+
+ friend bool operator<(int l, const copyable_int &r)
+ { return l < r.get_int(); }
+
+ friend std::size_t hash_value(const copyable_int &v)
+ { return (std::size_t)v.get_int(); }
+
+ private:
+ int m_int;
+};
+
+unsigned int copyable_int::count = 0;
+
+inline copyable_int produce_copyable_int()
+{ return copyable_int(); }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+ (std::basic_ostream<E, T> & os, copyable_int const & p)
+
+{
+ os << p.get_int();
+ return os;
+}
+
+template<>
+struct is_copyable<copyable_int>
+{
+ static const bool value = true;
+};
+
+class non_copymovable_int
+{
+ non_copymovable_int(const non_copymovable_int& mmi);
+ non_copymovable_int & operator= (const non_copymovable_int &mi);
+
+ public:
+
+ static unsigned int count;
+
+ non_copymovable_int()
+ : m_int(0)
+ { ++count; }
+
+ explicit non_copymovable_int(int a)
+ : m_int(a)
+ { ++count; }
+
+ ~non_copymovable_int()
+ { m_int = 0; --count; }
+
+ bool operator ==(const non_copymovable_int &mi) const
+ { return this->m_int == mi.m_int; }
+
+ bool operator !=(const non_copymovable_int &mi) const
+ { return this->m_int != mi.m_int; }
+
+ bool operator <(const non_copymovable_int &mi) const
+ { return this->m_int < mi.m_int; }
+
+ bool operator <=(const non_copymovable_int &mi) const
+ { return this->m_int <= mi.m_int; }
+
+ bool operator >=(const non_copymovable_int &mi) const
+ { return this->m_int >= mi.m_int; }
+
+ bool operator >(const non_copymovable_int &mi) const
+ { return this->m_int > mi.m_int; }
+
+ int get_int() const
+ { return m_int; }
+
+ friend bool operator==(const non_copymovable_int &l, int r)
+ { return l.get_int() == r; }
+
+ friend bool operator==(int l, const non_copymovable_int &r)
+ { return l == r.get_int(); }
+
+ friend bool operator<(const non_copymovable_int &l, int r)
+ { return l.get_int() < r; }
+
+ friend bool operator<(int l, const non_copymovable_int &r)
+ { return l < r.get_int(); }
+
+ friend std::size_t hash_value(const non_copymovable_int &v)
+ { return (std::size_t)v.get_int(); }
+
+ private:
+ int m_int;
+};
+
+unsigned int non_copymovable_int::count = 0;
+
+template<class T>
+struct life_count
+{
+ static unsigned check(unsigned) { return true; }
+};
+
+template<>
+struct life_count< movable_int >
+{
+ static unsigned check(unsigned c)
+ { return c == movable_int::count; }
+};
+
+template<>
+struct life_count< copyable_int >
+{
+ static unsigned check(unsigned c)
+ { return c == copyable_int::count; }
+};
+
+template<>
+struct life_count< movable_and_copyable_int >
+{
+ static unsigned check(unsigned c)
+ { return c == movable_and_copyable_int::count; }
+};
+
+template<>
+struct life_count< non_copymovable_int >
+{
+ static unsigned check(unsigned c)
+ { return c == non_copymovable_int::count; }
+};
+
+
+} //namespace test {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
diff --git a/src/boost/libs/container/test/node_handle_test.cpp b/src/boost/libs/container/test/node_handle_test.cpp
new file mode 100644
index 000000000..3c2637946
--- /dev/null
+++ b/src/boost/libs/container/test/node_handle_test.cpp
@@ -0,0 +1,633 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/core/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/node_handle.hpp>
+#include <boost/container/new_allocator.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/container/detail/pair_key_mapped_of_value.hpp>
+
+using namespace ::boost::container;
+
+enum EAllocState
+{
+ DefaultConstructed,
+ MoveConstructed,
+ MoveAssigned,
+ CopyConstructed,
+ CopyAssigned,
+ Swapped,
+ Destructed
+};
+
+template<class Node>
+class trace_allocator
+ : public new_allocator<Node>
+{
+ BOOST_COPYABLE_AND_MOVABLE(trace_allocator)
+
+ typedef new_allocator<Node> base_t;
+
+ public:
+
+ struct propagate_on_container_move_assignment
+ {
+ static const bool value = true;
+ };
+
+ struct propagate_on_container_swap
+ {
+ static const bool value = true;
+ };
+
+ //!Obtains an new_allocator that allocates
+ //!objects of type T2
+ template<class T2>
+ struct rebind
+ {
+ typedef trace_allocator<T2> other;
+ };
+
+ explicit trace_allocator(unsigned value = 999)
+ : m_state(DefaultConstructed), m_value(value)
+ {
+ ++count;
+ }
+
+ trace_allocator(BOOST_RV_REF(trace_allocator) other)
+ : base_t(boost::move(BOOST_MOVE_BASE(base_t, other))), m_state(MoveConstructed), m_value(other.m_value)
+ {
+ ++count;
+ }
+
+ trace_allocator(const trace_allocator &other)
+ : base_t(other), m_state(CopyConstructed), m_value(other.m_value)
+ {
+ ++count;
+ }
+
+ trace_allocator & operator=(BOOST_RV_REF(trace_allocator) other)
+ {
+ m_value = other.m_value;
+ m_state = MoveAssigned;
+ return *this;
+ }
+
+ template<class OtherNode>
+ trace_allocator(const trace_allocator<OtherNode> &other)
+ : m_state(CopyConstructed), m_value(other.m_value)
+ {
+ ++count;
+ }
+
+ template<class OtherNode>
+ trace_allocator & operator=(BOOST_COPY_ASSIGN_REF(trace_allocator<OtherNode>) other)
+ {
+ m_value = other.m_value;
+ m_state = CopyAssigned;
+ return *this;
+ }
+
+ ~trace_allocator()
+ {
+ m_value = 0u-1u;
+ m_state = Destructed;
+ --count;
+ }
+
+ void swap(trace_allocator &other)
+ {
+ boost::adl_move_swap(m_value, other.m_value);
+ m_state = other.m_state = Swapped;
+ }
+
+ friend void swap(trace_allocator &left, trace_allocator &right)
+ {
+ left.swap(right);
+ }
+
+ EAllocState m_state;
+ unsigned m_value;
+
+ static unsigned int count;
+
+ static void reset_count()
+ { count = 0; }
+};
+
+template<class Node>
+unsigned int trace_allocator<Node>::count = 0;
+
+template<class T>
+struct node
+{
+ typedef T value_type;
+ value_type value;
+
+ value_type &get_data() { return value; }
+ const value_type &get_data() const { return value; }
+
+ node()
+ {
+ ++count;
+ }
+
+ ~node()
+ {
+ --count;
+ }
+
+ static unsigned int count;
+
+ static void reset_count()
+ { count = 0; }
+};
+
+template<class T1, class T2>
+struct value
+{
+ T1 first;
+ T2 second;
+};
+
+template<class T>
+unsigned int node<T>::count = 0;
+
+
+//Common types
+typedef value<int, unsigned> test_pair;
+typedef pair_key_mapped_of_value<int, unsigned> key_mapped_t;
+typedef node<test_pair> node_t;
+typedef trace_allocator< node_t > node_alloc_t;
+typedef node_handle<node_alloc_t, void> node_handle_set_t;
+typedef node_handle<node_alloc_t, key_mapped_t> node_handle_map_t;
+typedef allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type value_allocator_type;
+
+void test_types()
+{
+ //set
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::value_type, test_pair>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::key_type, test_pair>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::mapped_type, test_pair>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::allocator_type, value_allocator_type>::value ));
+
+ //map
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::value_type, test_pair>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::key_type, int>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::mapped_type, unsigned>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::allocator_type, value_allocator_type>::value ));
+}
+
+void test_default_constructor()
+{
+ node_alloc_t::reset_count();
+ {
+ node_handle_set_t nh;
+ BOOST_TEST(node_alloc_t::count == 0);
+ }
+ BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_arg_constructor()
+{
+ //With non-null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_handle_set_t nh(new node_t, al);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 2);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ //With null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_handle_set_t nh(0, al);
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ BOOST_TEST(node_t::count == 0);
+ }
+ BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_move_constructor()
+{
+ //With non-null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_t *const from_ptr = new node_t;
+ node_handle_set_t nh(from_ptr, al);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 2);
+ {
+ node_handle_set_t nh2(boost::move(nh));
+ BOOST_TEST(nh.empty());
+ BOOST_TEST(!nh2.empty());
+ BOOST_TEST(nh2.get() == from_ptr);
+ BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 2);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ //With null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_handle_set_t nh;
+ {
+ node_handle_set_t nh2(boost::move(nh));
+ BOOST_TEST(nh.empty());
+ BOOST_TEST(nh2.empty());
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_related_constructor()
+{
+ //With non-null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_t *const from_ptr = new node_t;
+ node_handle_map_t nh(from_ptr, al);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 2);
+ {
+ node_handle_set_t nh2(boost::move(nh));
+ BOOST_TEST(nh.empty());
+ BOOST_TEST(!nh2.empty());
+ BOOST_TEST(nh2.get() == from_ptr);
+ BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 2);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ //With null pointer
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ {
+ const node_alloc_t al;
+ BOOST_TEST(node_alloc_t::count == 1);
+ {
+ node_handle_set_t nh;
+ {
+ node_handle_map_t nh2(boost::move(nh));
+ BOOST_TEST(nh.empty());
+ BOOST_TEST(nh2.empty());
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_move_assignment()
+{
+ //empty = full
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ node_t *const from_ptr = new node_t;
+ node_handle_set_t nh_from(from_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ node_handle_set_t nh_to;
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ nh_to = boost::move(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(!nh_to.empty());
+ BOOST_TEST(nh_to.get() == from_ptr);
+ BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+
+ //empty = empty
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_handle_set_t nh_from;
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ node_handle_set_t nh_to;
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ nh_to = boost::move(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+ }
+
+ //full = empty
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_handle_set_t nh_from;
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ node_handle_set_t nh_to(new node_t, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ nh_to = boost::move(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+ }
+
+ //full = full
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_t *const from_ptr = new node_t;
+ node_handle_set_t nh_from(from_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ node_handle_set_t nh_to(new node_t, node_alloc_t());
+ BOOST_TEST(node_t::count == 2);
+ BOOST_TEST(node_alloc_t::count == 2);
+
+ nh_to = boost::move(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(!nh_to.empty());
+ BOOST_TEST(nh_to.get() == from_ptr);
+ BOOST_TEST(nh_to.node_alloc().m_state == MoveAssigned);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+}
+
+void test_value_key_mapped()
+{
+ //value()
+ {
+ node_t *from_ptr = new node_t;
+ const node_handle_set_t nh_from(from_ptr, node_alloc_t());
+ from_ptr->value.first = -99;
+ from_ptr->value.second = 99;
+ BOOST_TEST(nh_from.value().first == -99);
+ BOOST_TEST(nh_from.value().second == 99);
+ }
+ //key()/mapped()
+ {
+ node_t *from_ptr = new node_t;
+ const node_handle_map_t nh_from(from_ptr, node_alloc_t());
+ from_ptr->value.first = -98;
+ from_ptr->value.second = 98;
+ BOOST_TEST(nh_from.key() == -98);
+ BOOST_TEST(nh_from.mapped() == 98);
+ }
+}
+
+void test_get_allocator()
+{
+ const node_handle_set_t nh(new node_t, node_alloc_t(888));
+ allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type a = nh.get_allocator();
+ BOOST_TEST(a.m_value == 888);
+}
+
+void test_bool_conversion_empty()
+{
+ const node_handle_set_t nh(new node_t, node_alloc_t(777));
+ const node_handle_set_t nh_null;
+ BOOST_TEST(nh && !nh_null);
+ BOOST_TEST(!(!nh || nh_null));
+ BOOST_TEST(!nh.empty() && nh_null.empty());
+ BOOST_TEST(!(nh.empty() || !nh_null.empty()));
+}
+
+void test_swap()
+{
+ //empty.swap(full)
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+ node_t *const from_ptr = new node_t;
+ node_handle_set_t nh_from(from_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ node_handle_set_t nh_to;
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ nh_to.swap(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(!nh_to.empty());
+ BOOST_TEST(nh_to.get() == from_ptr);
+ BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed);
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+
+ //empty.swap(empty)
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_handle_set_t nh_from;
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ node_handle_set_t nh_to;
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ nh_to.swap(nh_from);
+
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(nh_to.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+ }
+
+ //full.swap(empty)
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_handle_set_t nh_from;
+ BOOST_TEST(nh_from.empty());
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ node_t *const to_ptr = new node_t;
+ node_handle_set_t nh_to(to_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ nh_to.swap(nh_from);
+
+ BOOST_TEST(!nh_from.empty());
+ BOOST_TEST(nh_from.node_alloc().m_state == MoveConstructed);
+ BOOST_TEST(nh_from.get() == to_ptr);
+ BOOST_TEST(nh_to.empty());
+
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+
+ //full.swap(full)
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_t *const from_ptr = new node_t;
+ node_handle_set_t nh_from(from_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ node_t *const to_ptr = new node_t;
+ node_handle_set_t nh_to(to_ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 2);
+ BOOST_TEST(node_alloc_t::count == 2);
+
+ nh_to.swap(nh_from);
+
+ BOOST_TEST(!nh_from.empty());
+ BOOST_TEST(nh_from.get() == to_ptr);
+ BOOST_TEST(nh_from.node_alloc().m_state == Swapped);
+
+ BOOST_TEST(!nh_to.empty());
+ BOOST_TEST(nh_to.get() == from_ptr);
+ BOOST_TEST(nh_to.node_alloc().m_state == Swapped);
+
+ BOOST_TEST(node_t::count == 2);
+ BOOST_TEST(node_alloc_t::count == 2);
+ }
+}
+
+void test_get_release()
+{
+ //get()
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_t *const ptr = new node_t;
+ const node_handle_set_t nh(ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ BOOST_TEST(nh.get() == ptr);
+ BOOST_TEST(!nh.empty());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+ }
+ BOOST_TEST(node_t::count == 0);
+ BOOST_TEST(node_alloc_t::count == 0);
+
+ //release()
+ {
+ node_alloc_t::reset_count();
+ node_t::reset_count();
+
+ node_t *const ptr = new node_t;
+ node_handle_set_t nh(ptr, node_alloc_t());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 1);
+
+ BOOST_TEST(nh.release() == ptr);
+ BOOST_TEST(nh.empty());
+ BOOST_TEST(node_t::count == 1);
+ BOOST_TEST(node_alloc_t::count == 0);
+ delete ptr;
+ }
+ BOOST_TEST(node_t::count == 0);
+}
+
+int main()
+{
+ test_types();
+ test_default_constructor();
+ test_arg_constructor();
+ test_move_constructor();
+ test_related_constructor();
+ test_move_assignment();
+ test_value_key_mapped();
+ test_get_allocator();
+ test_bool_conversion_empty();
+ test_swap();
+ test_get_release();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/null_iterators_test.cpp b/src/boost/libs/container/test/null_iterators_test.cpp
new file mode 100644
index 000000000..f081dbe0e
--- /dev/null
+++ b/src/boost/libs/container/test/null_iterators_test.cpp
@@ -0,0 +1,96 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/string.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/set.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+#include <cstring>
+#include <new>
+
+using namespace boost::container;
+
+typedef boost::container::dtl::aligned_storage<sizeof(void*)*4>::type buffer_t;
+
+static buffer_t buffer_0x00;
+static buffer_t buffer_0xFF;
+
+template<class Iterator>
+const Iterator &on_0x00_buffer()
+{
+ BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
+ return * ::new(std::memset(&buffer_0x00, 0x00, sizeof(buffer_0x00))) Iterator();
+}
+
+template<class Iterator>
+const Iterator &on_0xFF_buffer()
+{
+ BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
+ return * ::new(std::memset(&buffer_0xFF, 0xFF, sizeof(buffer_0xFF))) Iterator();
+}
+
+namespace boost {
+namespace container {
+namespace test {
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator)
+
+}}} //namespace boost::container::test {
+
+template<class Container>
+void check_null_iterators()
+{
+ typedef typename Container::iterator iterator;
+ typedef typename Container::const_iterator const_iterator;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::test::, Container
+ ,reverse_iterator, iterator) reverse_iterator;
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::test::, Container
+ ,const_reverse_iterator, const_iterator) const_reverse_iterator;
+
+ BOOST_TEST(on_0xFF_buffer<iterator>() == on_0x00_buffer<iterator>());
+ BOOST_TEST(on_0xFF_buffer<const_iterator>() == on_0x00_buffer<const_iterator>());
+ BOOST_TEST(on_0xFF_buffer<reverse_iterator>() == on_0x00_buffer<reverse_iterator>());
+ BOOST_TEST(on_0xFF_buffer<const_reverse_iterator>() == on_0x00_buffer<const_reverse_iterator>());
+}
+
+int main()
+{
+ check_null_iterators< vector<int> >();
+ check_null_iterators< deque<int> >();
+ check_null_iterators< stable_vector<int> >();
+ check_null_iterators< static_vector<int, 1> >();
+ check_null_iterators< string >();
+ check_null_iterators< list<int> >();
+ check_null_iterators< slist<int> >();
+ check_null_iterators< map<int, int> >();
+ check_null_iterators< multimap<int, int> >();
+ check_null_iterators< set<int> >();
+ check_null_iterators< multiset<int> >();
+ check_null_iterators< flat_set<int> >();
+ check_null_iterators< flat_multiset<int> >();
+ check_null_iterators< flat_map<int, int> >();
+ check_null_iterators< flat_multimap<int, int> >();
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/pair_test.cpp b/src/boost/libs/container/test/pair_test.cpp
new file mode 100644
index 000000000..5ead7a450
--- /dev/null
+++ b/src/boost/libs/container/test/pair_test.cpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include "movable_int.hpp"
+#include "emplace_test.hpp"
+#include<boost/move/utility_core.hpp>
+#include<boost/move/detail/fwd_macros.hpp>
+#include<boost/core/lightweight_test.hpp>
+
+//non_copymovable_int
+//copyable_int
+//movable_int
+//movable_and_copyable_int
+
+
+#include <boost/tuple/tuple.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
+#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+#endif
+
+#if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+#include <tuple>
+#endif
+
+using namespace ::boost::container;
+
+int main ()
+{
+ {
+ dtl::pair<test::non_copymovable_int, test::non_copymovable_int> p1;
+ dtl::pair<test::copyable_int, test::copyable_int> p2;
+ dtl::pair<test::movable_int, test::movable_int> p3;
+ dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4;
+ }
+ { //Constructible from two values
+ dtl::pair<test::non_copymovable_int, test::non_copymovable_int> p1(1, 2);
+ dtl::pair<test::copyable_int, test::copyable_int> p2(1, 2);
+ dtl::pair<test::movable_int, test::movable_int> p3(1, 2);
+ dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4(1, 2);
+ }
+
+ { //Constructible from internal types
+ dtl::pair<test::copyable_int, test::copyable_int> p2(test::copyable_int(1), test::copyable_int(2));
+ {
+ test::movable_int a(1), b(2);
+ dtl::pair<test::movable_int, test::movable_int> p3(::boost::move(a), ::boost::move(b));
+ }
+ {
+ test::movable_and_copyable_int a(1), b(2);
+ dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4(::boost::move(a), ::boost::move(b));
+ }
+ }
+ { //piecewise construct from boost tuple
+ using namespace boost::tuples;
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<>());
+ BOOST_TEST(p.first == 0);
+ BOOST_TEST(p.second == 0.f);
+ }
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<float>(2.f));
+ BOOST_TEST(p.first == 0);
+ BOOST_TEST(p.second == 2.f);
+ }
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<int>(2), tuple<float>(1.f));
+ BOOST_TEST(p.first == 2);
+ BOOST_TEST(p.second == 1.f);
+ }
+ {
+ boost::container::dtl::pair
+ < boost::container::dtl::pair<int, float>
+ , boost::container::dtl::pair<double, char>
+ > p(piecewise_construct, tuple<int, float>(3, 4.f), tuple<double, char>(8.,'a'));
+ BOOST_TEST(p.first.first == 3);
+ BOOST_TEST(p.first.second == 4.f);
+ BOOST_TEST(p.second.first == 8.);
+ BOOST_TEST(p.second.second == 'a');
+ }
+ {
+ boost::container::dtl::pair
+ < tuple<int, float, double>
+ , char
+ > p(piecewise_construct, tuple<int, float, double>(3, 16.f, 32.), tuple<char>('b'));
+ BOOST_TEST(p.first.get<0>() == 3);
+ BOOST_TEST(p.first.get<1>() == 16.f);
+ BOOST_TEST(p.first.get<2>() == 32.);
+ BOOST_TEST(p.second == 'b');
+ }
+ }
+ #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+ { //piecewise construct from std tuple
+ using std::tuple;
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<>());
+ BOOST_TEST(p.first == 0);
+ BOOST_TEST(p.second == 0.f);
+ }
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<float>(2.f));
+ BOOST_TEST(p.first == 0);
+ BOOST_TEST(p.second == 2.f);
+ }
+ {
+ boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<int>(2), tuple<float>(1.f));
+ BOOST_TEST(p.first == 2);
+ BOOST_TEST(p.second == 1.f);
+ }
+ {
+ boost::container::dtl::pair
+ < boost::container::dtl::pair<int, float>
+ , boost::container::dtl::pair<double, char>
+ > p(piecewise_construct, tuple<int, float>(3, 4.f), tuple<double, char>(8.,'a'));
+ BOOST_TEST(p.first.first == 3);
+ BOOST_TEST(p.first.second == 4.f);
+ BOOST_TEST(p.second.first == 8.);
+ BOOST_TEST(p.second.second == 'a');
+ }
+ {
+ boost::container::dtl::pair
+ < tuple<int, float, double>
+ , char
+ > p(piecewise_construct, tuple<int, float, double>(3, 16.f, 32.), tuple<char>('b'));
+ BOOST_TEST(std::get<0>(p.first) == 3);
+ BOOST_TEST(std::get<1>(p.first) == 16.f);
+ BOOST_TEST(std::get<2>(p.first) == 32.);
+ BOOST_TEST(p.second == 'b');
+ }
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ typedef dtl::pair<test::movable_int, test::movable_int> movable_pair_t;
+ typedef dtl::pair<movable_pair_t, movable_pair_t> movable_pair_pair_t;
+ test::movable_int a(1), b(2), c(3), d(4);
+ movable_pair_pair_t p( piecewise_construct
+ , dtl::forward_as_tuple_impl(boost::move(a), boost::move(b))
+ , dtl::forward_as_tuple_impl(boost::move(c), boost::move(d))
+ );
+ BOOST_TEST(p.first.first == 1);
+ BOOST_TEST(p.first.second == 2);
+ BOOST_TEST(p.second.first == 3);
+ BOOST_TEST(p.second.second == 4);
+ #endif
+ }
+ #endif //#!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
+ return ::boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/pmr_deque_test.cpp b/src/boost/libs/container/test/pmr_deque_test.cpp
new file mode 100644
index 000000000..15c67e2a6
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_deque_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/deque.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef deque<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_flat_map_test.cpp b/src/boost/libs/container/test/pmr_flat_map_test.cpp
new file mode 100644
index 000000000..f98e497bf
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_flat_map_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/flat_map.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef flat_map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<int, float> > > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map_of<int, float>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map<int, float> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_flat_set_test.cpp b/src/boost/libs/container/test/pmr_flat_set_test.cpp
new file mode 100644
index 000000000..5c9efe1a7
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_flat_set_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/flat_set.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef flat_set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_list_test.cpp b/src/boost/libs/container/test/pmr_list_test.cpp
new file mode 100644
index 000000000..794ccf524
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_list_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/list.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef list<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_map_test.cpp b/src/boost/libs/container/test/pmr_map_test.cpp
new file mode 100644
index 000000000..5db3f1091
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_map_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/map.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<const int, float> > > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map_of<int, float>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map<int, float> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_set_test.cpp b/src/boost/libs/container/test/pmr_set_test.cpp
new file mode 100644
index 000000000..3093fd434
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_set_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/set.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_slist_test.cpp b/src/boost/libs/container/test/pmr_slist_test.cpp
new file mode 100644
index 000000000..ed4b5ae9c
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_slist_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/slist.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::slist<empty>;
+
+int main()
+{
+ ::boost::container::slist<empty> dummy;
+ (void)dummy;
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_small_vector_test.cpp b/src/boost/libs/container/test/pmr_small_vector_test.cpp
new file mode 100644
index 000000000..334588da3
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_small_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/small_vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef small_vector<int, 2, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector_of<int, 2>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector<int, 2> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_stable_vector_test.cpp b/src/boost/libs/container/test/pmr_stable_vector_test.cpp
new file mode 100644
index 000000000..246f071c3
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_stable_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/stable_vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef stable_vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_static_vector_test.cpp b/src/boost/libs/container/test/pmr_static_vector_test.cpp
new file mode 100644
index 000000000..6681f7cd2
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_static_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/static_vector.hpp>
+
+struct empty
+{
+ friend bool operator == (const empty &, const empty &){ return true; }
+ friend bool operator < (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::static_vector<empty, 2>;
+
+int main()
+{
+ ::boost::container::static_vector<empty, 2> dummy;
+ (void)dummy;
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_string_test.cpp b/src/boost/libs/container/test/pmr_string_test.cpp
new file mode 100644
index 000000000..c8d81a5ba
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_string_test.cpp
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/string.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef basic_string<char, std::char_traits<char>, pmr::polymorphic_allocator<char> > string_t;
+ typedef basic_string<wchar_t, std::char_traits<wchar_t>, pmr::polymorphic_allocator<wchar_t> > wstring_t;
+ BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string>::value ));
+ BOOST_STATIC_ASSERT(( is_same<string_t, pmr::basic_string_of<char>::type>::value ));
+ BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring>::value ));
+ BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::basic_string_of<wchar_t>::type>::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string >::value ));
+ BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/pmr_vector_test.cpp b/src/boost/libs/container/test/pmr_vector_test.cpp
new file mode 100644
index 000000000..293291ce0
--- /dev/null
+++ b/src/boost/libs/container/test/pmr_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+ using namespace boost::container;
+ using boost::container::dtl::is_same;
+
+ typedef vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector_of<int>::type >::value ));
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector<int> >::value ));
+ #endif
+ return 0;
+}
diff --git a/src/boost/libs/container/test/polymorphic_allocator_test.cpp b/src/boost/libs/container/test/polymorphic_allocator_test.cpp
new file mode 100644
index 000000000..10899cac1
--- /dev/null
+++ b/src/boost/libs/container/test/polymorphic_allocator_test.cpp
@@ -0,0 +1,198 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include "derived_from_memory_resource.hpp"
+#include "propagation_test_allocator.hpp"
+
+using namespace boost::container::pmr;
+using namespace boost::container;
+
+void test_default_constructor()
+{
+ polymorphic_allocator<int> a;
+ BOOST_TEST(a.resource() == get_default_resource());
+}
+
+void test_resource_constructor()
+{
+ polymorphic_allocator<int> a(0);
+ BOOST_TEST(a.resource() == get_default_resource());
+
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> b(&d);
+ BOOST_TEST(&d == b.resource());
+}
+
+void test_copy_constructor()
+{
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> b(&d);
+ polymorphic_allocator<int> c(b);
+ BOOST_TEST(b.resource() == c.resource());
+}
+
+void test_copy_assignment()
+{
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> b(&d);
+ polymorphic_allocator<int> c;
+ BOOST_TEST(c.resource() == get_default_resource());
+ c = b;
+ BOOST_TEST(c.resource() == b.resource());
+}
+
+void test_allocate()
+{
+ int dummy;
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> p(&d);
+ d.reset();
+ d.do_allocate_return = &dummy;
+ p.allocate(2);
+ BOOST_TEST(d.do_allocate_called == true);
+ BOOST_TEST(d.do_allocate_return == &dummy);
+ //It shall allocate 2*sizeof(int), alignment_of<int>
+ BOOST_TEST(d.do_allocate_bytes == 2*sizeof(int));
+ BOOST_TEST(d.do_allocate_alignment == dtl::alignment_of<int>::value);
+}
+
+void test_deallocate()
+{
+ int dummy;
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> p(&d);
+ d.reset();
+ p.deallocate(&dummy, 3);
+ BOOST_TEST(d.do_deallocate_called == true);
+ //It shall deallocate 2*sizeof(int), alignment_of<int>
+ BOOST_TEST(d.do_deallocate_p == &dummy);
+ BOOST_TEST(d.do_deallocate_bytes == 3*sizeof(int));
+ BOOST_TEST(d.do_deallocate_alignment == dtl::alignment_of<int>::value);
+}
+
+void test_construct()
+{
+ //0 arg
+ {
+ typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value);
+ BOOST_TEST(value.construction_type == NotUsesAllocator);
+ BOOST_TEST(value.value == 0);
+ value.~value_type();
+ }
+ {
+ typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value);
+ BOOST_TEST(value.construction_type == ConstructiblePrefix);
+ BOOST_TEST(value.value == 0);
+ value.~value_type();
+ }
+ {
+ typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value);
+ BOOST_TEST(value.construction_type == ConstructibleSuffix);
+ BOOST_TEST(value.value == 0);
+ value.~value_type();
+ }
+ //1 arg
+ {
+ typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value, 2);
+ BOOST_TEST(value.construction_type == NotUsesAllocator);
+ BOOST_TEST(value.value == 2);
+ value.~value_type();
+ }
+ {
+ typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value, 3);
+ BOOST_TEST(value.construction_type == ConstructiblePrefix);
+ BOOST_TEST(value.value == 3);
+ value.~value_type();
+ }
+ {
+ typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
+ value_type value;
+ value.~value_type();
+ polymorphic_allocator<int> pa;
+ pa.construct(&value, 4);
+ BOOST_TEST(value.construction_type == ConstructibleSuffix);
+ BOOST_TEST(value.value == 4);
+ value.~value_type();
+ }
+}
+
+struct char_holder
+{
+ char m_char;
+ ~char_holder()
+ { destructor_called = true; }
+ static bool destructor_called;
+};
+
+bool char_holder::destructor_called = false;
+
+void test_destroy()
+{
+ char_holder ch;
+ polymorphic_allocator<int> p;
+ BOOST_TEST(char_holder::destructor_called == false);
+ p.destroy(&ch);
+ BOOST_TEST(char_holder::destructor_called == true);
+}
+
+void test_select_on_container_copy_construction()
+{
+ //select_on_container_copy_construction shall return
+ //a default constructed polymorphic_allocator
+ //which uses the default resource.
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> p(&d);
+ BOOST_TEST(get_default_resource() == p.select_on_container_copy_construction().resource());
+}
+
+void test_resource()
+{
+ derived_from_memory_resource d;
+ polymorphic_allocator<int> p(&d);
+ BOOST_TEST(&d == p.resource());
+}
+
+int main()
+{
+ test_default_constructor();
+ test_resource_constructor();
+ test_copy_constructor();
+ test_copy_assignment();
+ test_allocate();
+ test_deallocate();
+ test_construct();
+ test_destroy();
+ test_select_on_container_copy_construction();
+ test_resource();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/pool_resource_test.hpp b/src/boost/libs/container/test/pool_resource_test.hpp
new file mode 100644
index 000000000..110274e32
--- /dev/null
+++ b/src/boost/libs/container/test/pool_resource_test.hpp
@@ -0,0 +1,493 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/intrusive/detail/math.hpp>
+
+#include "derived_from_memory_resource.hpp"
+#include "memory_resource_logger.hpp"
+
+using namespace boost::container::pmr;
+
+template<class PoolResource>
+struct derived_from_pool_resource
+ : public PoolResource
+{
+ derived_from_pool_resource(const pool_options& opts, memory_resource* upstream)
+ : PoolResource(opts, upstream)
+ {}
+
+ explicit derived_from_pool_resource(memory_resource *p)
+ : PoolResource(p)
+ {}
+
+ explicit derived_from_pool_resource(const pool_options &opts)
+ : PoolResource(opts)
+ {}
+
+ derived_from_pool_resource()
+ : PoolResource()
+ {}
+
+ using PoolResource::do_allocate;
+ using PoolResource::do_deallocate;
+ using PoolResource::do_is_equal;
+};
+
+template<class PoolResource>
+void test_default_constructor()
+{
+ //With default options/resource
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ PoolResource m;
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+template<class PoolResource>
+void test_upstream_constructor()
+{
+ //With a resource, default options
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ PoolResource m(&dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+template<class PoolResource>
+void test_options_constructor()
+{
+ //Default options
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ pool_options opts;
+ PoolResource m(opts);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ }
+ //Too large option values
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ pool_options opts;
+ opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
+ opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
+ PoolResource m(opts);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ }
+ //Too small option values
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ pool_options opts;
+ opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
+ PoolResource m(opts);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ }
+ //In range option values
+ {
+ memory_resource_logger mrl;
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ set_default_resource(&mrl);
+ pool_options opts;
+ opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
+ opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
+ PoolResource m(opts);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == get_default_resource());
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(mrl.m_info.size() == 0u);
+ }
+}
+
+template<class PoolResource>
+void test_options_upstream_constructor()
+{
+ //Default options
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ pool_options opts;
+ PoolResource m(opts, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+ //Too large option values
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ pool_options opts;
+ opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
+ opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
+ PoolResource m(opts, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+ //Too small option values
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ pool_options opts;
+ opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
+ PoolResource m(opts, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+ //In range option values
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ pool_options opts;
+ opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
+ opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
+ PoolResource m(opts, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ //max blocks is unchanged in this implementation
+ BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+ //largest block is rounded to pow2
+ BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+template<class PoolResource>
+void test_options()
+{
+ //In range option values
+ {
+ derived_from_memory_resource dmr;
+ dmr.reset();
+ pool_options opts;
+ opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk/2u;
+ opts.largest_required_pool_block = (pool_options_default_largest_required_pool_block
+ - pool_options_minimum_largest_required_pool_block) | std::size_t(1); //guaranteed to be non power of 2.
+ PoolResource m(opts, &dmr);
+ //test postconditions
+ BOOST_TEST(m.upstream_resource() == &dmr);
+ //max blocks is unchanged in this implementation
+ BOOST_TEST(m.options().max_blocks_per_chunk == opts.max_blocks_per_chunk);
+ //largest block is rounded to pow2
+ BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
+ //test it does not allocate any memory
+ BOOST_TEST(dmr.do_allocate_called == false);
+ }
+}
+
+template<class PoolResource>
+void test_do_allocate_deallocate()
+{
+ memory_resource_logger mrl;
+ {
+ derived_from_pool_resource<PoolResource> dmbr(&mrl);
+ {
+ //First block from pool 0
+ dmbr.do_allocate(1, 1);
+ //It should allocate the pool array plus an initial block
+ BOOST_TEST(mrl.m_info.size() == 2u);
+ //Second block from pool 0
+ dmbr.do_allocate(1, 1);
+ //It should allocate again (with 2 chunks per block)
+ BOOST_TEST(mrl.m_info.size() == 3u);
+ //Third block from pool 0
+ dmbr.do_allocate(1, 1);
+ //It should NOT allocate again (previous was a 2 block chunk)
+ BOOST_TEST(mrl.m_info.size() == 3u);
+ }
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+
+ //Allocate and deallocate from the same chunk to test block caching
+ {
+ derived_from_pool_resource<PoolResource> dmbr(&mrl);
+ {
+ //First block from pool 0
+ void *p = dmbr.do_allocate(1, 1);
+ //It should allocate the pool array plus an initial block
+ BOOST_TEST(mrl.m_info.size() == 2u);
+ //No cached, as initial blocks per chunk is 1
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+ //Deallocate and allocate again
+ dmbr.do_deallocate(p, 1, 1);
+ //Cached
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
+ p = dmbr.do_allocate(1, 1);
+ //Reused
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+ //It should have NOT allocated (block reuse)
+ BOOST_TEST(mrl.m_info.size() == 2u);
+
+ //Allocate again 2 times (a 2 block chunk is exhausted)
+ void *p2 = dmbr.do_allocate(1, 1);
+ //1 left cached
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
+ void *p3 = dmbr.do_allocate(1, 1);
+ //Cache exhausted
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+ //Single chunk allocation happened
+ BOOST_TEST(mrl.m_info.size() == 3u);
+
+ //Now deallocate all (no memory is freed, all cached)
+ dmbr.do_deallocate(p2, 1, 1);
+ dmbr.do_deallocate(p3, 1, 1);
+ dmbr.do_deallocate(p, 1, 1);
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == 3u);
+ BOOST_TEST(mrl.m_info.size() == 3u);
+ }
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+
+ //Now test max block per chunk
+ {
+ pool_options opts;
+ //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+ opts.max_blocks_per_chunk = 32u;
+ derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+ {
+ std::size_t loops = opts.max_blocks_per_chunk*2-1u;
+ while(loops--){
+ dmbr.do_allocate(1, 1);
+ }
+ //pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
+ const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
+ BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
+ //Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
+ dmbr.do_allocate(1, 1);
+ BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+ //Exhaust the chunk and allocate a new one, test max_blocks_per_chunk is not passed again
+ loops = opts.max_blocks_per_chunk;
+ while(loops--){
+ dmbr.do_allocate(1, 1);
+ }
+ BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 2u);
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+ }
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+
+ //Now test max block per chunk
+ {
+ pool_options opts;
+ //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+ opts.max_blocks_per_chunk = 32u;
+ derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+ {
+ std::size_t loops = opts.max_blocks_per_chunk*2-1u;
+ while(loops--){
+ dmbr.do_allocate(1, 1);
+ }
+ //pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
+ BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
+ const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
+ BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
+ //Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
+ dmbr.do_allocate(1, 1);
+ BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
+ BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
+ BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+ }
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+
+ //Now test different pool sizes
+ {
+ pool_options opts;
+ //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+ opts.max_blocks_per_chunk = 1u;
+ derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+ const pool_options &final_opts = dmbr.options();
+
+ //Force pool creation
+ dmbr.do_deallocate(dmbr.do_allocate(1, 1), 1, 1);
+ //pool array plus first pool's chunk allocation
+ BOOST_TEST(mrl.m_info.size() == 2u);
+ //pool count must be:
+ // log2(the maximum block) - log2(the minimum block) + 1. Example if minimum block is 8, and maximum 32:
+ // log(32) - log2(8) + 1u = 3 pools (block sizes: 8, 16, and 32)
+ const std::size_t minimum_size = dmbr.pool_block(0u);
+ const std::size_t maximum_size = final_opts.largest_required_pool_block;
+ BOOST_TEST(dmbr.pool_count() == (1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size)));
+ for(std::size_t i = 0, s = minimum_size, max = dmbr.pool_count(); i != max; ++i, s*=2){
+ //Except in the first pool, each cache should be empty
+ BOOST_TEST(dmbr.pool_cached_blocks(i) == std::size_t(i == 0));
+ dmbr.do_deallocate(dmbr.do_allocate(s/2+1, 1), s/2+1, 1);
+ dmbr.do_deallocate(dmbr.do_allocate(s-1, 1), s-1, 1);
+ dmbr.do_deallocate(dmbr.do_allocate(s, 1), s, 1);
+ //pool array plus each previous chunk allocation
+ BOOST_TEST(mrl.m_info.size() == (1u + i + 1u));
+ //as we limited max_blocks_per_chunk to 1, no cached blocks should be available except one
+ BOOST_TEST(dmbr.pool_cached_blocks(i) == 1u);
+ }
+ //Now test out of maximum values, which should go directly to upstream
+ //it should be directly deallocated.
+ void *p = dmbr.do_allocate(maximum_size+1, 1);
+ BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count() + 1u));
+ dmbr.do_deallocate(p, maximum_size+1, 1);
+ BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count()));
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+template<class PoolResource>
+void test_do_is_equal()
+{
+ //`this == dynamic_cast<const PoolResource*>(&other)`.
+ memory_resource_logger mrl;
+ derived_from_pool_resource<PoolResource> dmbr(&mrl);
+ derived_from_pool_resource<PoolResource> dmbr2(&mrl);
+ BOOST_TEST(true == dmbr.do_is_equal(dmbr));
+ BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
+ //A different type should be always different
+ derived_from_memory_resource dmr;
+ BOOST_TEST(false == dmbr.do_is_equal(dmr));
+}
+
+template<class PoolResource>
+void test_release()
+{
+ memory_resource_logger mrl;
+ {
+ pool_options opts;
+ //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+ opts.max_blocks_per_chunk = 4u;
+ derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+ const pool_options &final_opts = dmbr.options();
+ const std::size_t minimum_size = dmbr.pool_block(0u);
+ const std::size_t maximum_size = final_opts.largest_required_pool_block;
+ const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
+
+ std::size_t expected_memory_allocs = 0;
+ for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
+ for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+ dmbr.do_allocate(s, 1);
+ }
+ //One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
+ expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
+ //pool array plus each previous chunk allocation
+ BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
+ }
+ //Now with out-of-pool sizes
+ for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+ dmbr.do_allocate(maximum_size+1, 1);
+ BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
+ }
+ //Now release memory and check all memory allocated through do_allocate was deallocated to upstream
+ dmbr.release();
+ BOOST_TEST(mrl.m_info.size() == 1u);
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+template<class PoolResource>
+void test_destructor()
+{
+ memory_resource_logger mrl;
+ {
+ pool_options opts;
+ //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+ opts.max_blocks_per_chunk = 4u;
+ derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+ const pool_options &final_opts = dmbr.options();
+ const std::size_t minimum_size = dmbr.pool_block(0u);
+ const std::size_t maximum_size = final_opts.largest_required_pool_block;
+ const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
+
+ std::size_t expected_memory_allocs = 0;
+ for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
+ for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+ dmbr.do_allocate(s, 1);
+ }
+ //One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
+ expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
+ //pool array plus each previous chunk allocation
+ BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
+ }
+ //Now with out-of-pool sizes
+ for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+ dmbr.do_allocate(maximum_size+1, 1);
+ BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
+ }
+ //Don't release, all memory, including internal allocations, should be automatically
+ //released after the destructor is run
+ }
+ BOOST_TEST(mrl.m_mismatches == 0u);
+ BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+
+template<class PoolResource>
+void test_pool_resource()
+{
+ test_options_upstream_constructor<PoolResource>();
+ test_default_constructor<PoolResource>();
+ test_upstream_constructor<PoolResource>();
+ test_options_constructor<PoolResource>();
+ test_options<PoolResource>();
+ test_do_allocate_deallocate<PoolResource>();
+ test_do_is_equal<PoolResource>();
+ test_release<PoolResource>();
+ test_destructor<PoolResource>();
+}
diff --git a/src/boost/libs/container/test/print_container.hpp b/src/boost/libs/container/test/print_container.hpp
new file mode 100644
index 000000000..2e49ec60e
--- /dev/null
+++ b/src/boost/libs/container/test/print_container.hpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_PRINTCONTAINER_HPP
+#define BOOST_PRINTCONTAINER_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <iostream>
+
+namespace boost{
+namespace container {
+namespace test{
+
+//Function to dump data
+template<class MyBoostCont
+ ,class MyStdCont>
+void PrintContainers(MyBoostCont *boostcont, MyStdCont *stdcont)
+{
+ typename MyBoostCont::iterator itboost = boostcont->begin(), itboostend = boostcont->end();
+ typename MyStdCont::iterator itstd = stdcont->begin(), itstdend = stdcont->end();
+
+ std::cout << "MyBoostCont" << std::endl;
+ for(; itboost != itboostend; ++itboost){
+ std::cout << *itboost << std::endl;
+ }
+ std::cout << "MyStdCont" << std::endl;
+
+ for(; itstd != itstdend; ++itstd){
+ std::cout << *itstd << std::endl;
+ }
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_PRINTCONTAINER_HPP
diff --git a/src/boost/libs/container/test/propagate_allocator_test.hpp b/src/boost/libs/container/test/propagate_allocator_test.hpp
new file mode 100644
index 000000000..e3a504818
--- /dev/null
+++ b/src/boost/libs/container/test/propagate_allocator_test.hpp
@@ -0,0 +1,368 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
+#define BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "dummy_test_allocator.hpp"
+
+#include <iostream>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class Selector>
+struct alloc_propagate_base;
+
+template<class T, class Allocator, class Selector>
+class alloc_propagate_wrapper
+ : public alloc_propagate_base<Selector>::template apply<T, Allocator>::type
+{
+ BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper)
+
+ public:
+ typedef typename alloc_propagate_base
+ <Selector>::template apply<T, Allocator>::type Base;
+
+ typedef typename Base::allocator_type allocator_type;
+ typedef typename Base::value_type value_type;
+ typedef typename Base::size_type size_type;
+
+ alloc_propagate_wrapper()
+ : Base()
+ {}
+
+ explicit alloc_propagate_wrapper(const allocator_type &a)
+ : Base(a)
+ {}
+/*
+ //sequence containers only
+ explicit alloc_propagate_wrapper(size_type n, const value_type &v, const allocator_type &a)
+ : Base(n, v, a)
+ {}
+
+ alloc_propagate_wrapper(size_type n, const allocator_type &a)
+ : Base(n, a)
+ {}*/
+
+ template<class Iterator>
+ alloc_propagate_wrapper(Iterator b, Iterator e, const allocator_type &a)
+ : Base(b, e, a)
+ {}
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ alloc_propagate_wrapper(std::initializer_list<value_type> il, const allocator_type& a)
+ : Base(il, a)
+ {}
+/*
+ //associative containers only
+ alloc_propagate_wrapper(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : Base(il, comp, a)
+ {}*/
+
+ #endif
+
+ alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
+ : Base(x)
+ {}
+
+ alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
+ : Base(x, a)
+ {}
+
+ alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
+ : Base(boost::move(static_cast<Base&>(x)))
+ {}
+
+ alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a)
+ : Base(boost::move(static_cast<Base&>(x)), a)
+ {}
+
+ alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
+ { this->Base::operator=((const Base &)x); return *this; }
+
+ alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x)
+ { this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
+
+ void swap(alloc_propagate_wrapper &x)
+ { this->Base::swap(x); }
+};
+
+template<class T>
+struct get_real_stored_allocator
+{
+ typedef typename T::stored_allocator_type type;
+};
+
+template<class Container>
+void test_propagate_allocator_allocator_arg();
+
+template<class Selector>
+bool test_propagate_allocator()
+{
+ {
+ typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate;
+ typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector> PropagateCont;
+ typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
+ {
+ //////////////////////////////////////////
+ //Test AlwaysPropagate allocator propagation
+ //////////////////////////////////////////
+
+ //default constructor
+ StoredAllocator::reset_unique_id(111);
+ PropagateCont c; //stored 112
+ BOOST_TEST (c.get_stored_allocator().id_ == 112);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //copy constructor
+ StoredAllocator::reset_unique_id(222);
+ PropagateCont c; //stored 223
+ BOOST_TEST (c.get_stored_allocator().id_ == 223);
+ //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
+ //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
+ PropagateCont c2(c); //should propagate 223
+ BOOST_TEST (c2.get_stored_allocator().id_ == 223);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //move constructor
+ StoredAllocator::reset_unique_id(333);
+ PropagateCont c; //stored 334
+ BOOST_TEST (c.get_stored_allocator().id_ == 334);
+ PropagateCont c2(boost::move(c)); //should propagate 334
+ BOOST_TEST (c2.get_stored_allocator().id_ == 334);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //copy assign
+ StoredAllocator::reset_unique_id(444);
+ PropagateCont c; //stored 445
+ BOOST_TEST (c.get_stored_allocator().id_ == 445);
+ PropagateCont c2; //stored 446
+ BOOST_TEST (c2.get_stored_allocator().id_ == 446);
+ c2 = c; //should propagate 445
+ BOOST_TEST (c2.get_stored_allocator().id_ == 445);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //move assign
+ StoredAllocator::reset_unique_id(555);
+ PropagateCont c; //stored 556
+ BOOST_TEST (c.get_stored_allocator().id_ == 556);
+ PropagateCont c2; //stored 557
+ BOOST_TEST (c2.get_stored_allocator().id_ == 557);
+ c = boost::move(c2); //should propagate 557
+ BOOST_TEST (c.get_stored_allocator().id_ == 557);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 1);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //swap
+ StoredAllocator::reset_unique_id(666);
+ PropagateCont c; //stored 667
+ BOOST_TEST (c.get_stored_allocator().id_ == 667);
+ PropagateCont c2; //stored 668
+ BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+ c.swap(c2);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 1);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 1);
+ }
+ //And now allocator argument constructors
+ test_propagate_allocator_allocator_arg<PropagateCont>();
+ }
+
+ //////////////////////////////////////////
+ //Test NeverPropagate allocator propagation
+ //////////////////////////////////////////
+ {
+ typedef propagation_test_allocator<char, false, false, false, false> NeverPropagate;
+ typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
+ typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
+ {
+ //default constructor
+ StoredAllocator::reset_unique_id(111);
+ NoPropagateCont c; //stored 112
+ BOOST_TEST (c.get_stored_allocator().id_ == 112);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //copy constructor
+ //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
+ //For allocators that don't copy in select_on_container_copy_construction we must have a default
+ //construction
+ StoredAllocator::reset_unique_id(222);
+ NoPropagateCont c; //stored 223
+ BOOST_TEST (c.get_stored_allocator().id_ == 223);
+ NoPropagateCont c2(c); //should NOT propagate 223
+ BOOST_TEST (c2.get_stored_allocator().id_ == 224);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //move constructor
+ StoredAllocator::reset_unique_id(333);
+ NoPropagateCont c; //stored 334
+ BOOST_TEST (c.get_stored_allocator().id_ == 334);
+ NoPropagateCont c2(boost::move(c)); // should NOT propagate 334
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //copy assign
+ StoredAllocator::reset_unique_id(444);
+ NoPropagateCont c; //stored 445
+ NoPropagateCont c2; //stored 446
+ c2 = c; // should NOT propagate 445
+ BOOST_TEST (c2.get_stored_allocator().id_ == 446);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //move assign
+ StoredAllocator::reset_unique_id(555);
+ NoPropagateCont c; //stored 556
+ NoPropagateCont c2; //stored 557
+ c2 = c; // should NOT propagate 556
+ BOOST_TEST (c2.get_stored_allocator().id_ == 557);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //swap
+ StoredAllocator::reset_unique_id(666);
+ NoPropagateCont c; //stored 667
+ BOOST_TEST (c.get_stored_allocator().id_ == 667);
+ NoPropagateCont c2; //stored 668
+ BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+ c2.swap(c); // should NOT swap 667 and 668
+ BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ BOOST_TEST (c.get_stored_allocator().id_ == 667);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+ }
+ //And now allocator argument constructors
+ test_propagate_allocator_allocator_arg<NoPropagateCont>();
+ }
+
+ return report_errors() == 0;
+}
+
+template<class Container>
+void test_propagate_allocator_allocator_arg()
+{
+ typedef typename Container::allocator_type allocator_type;
+ typedef typename get_real_stored_allocator<typename Container::Base>::type StoredAllocator;
+
+ { //The allocator must be always propagated
+ //allocator constructor
+ allocator_type::reset_unique_id(111);
+ const allocator_type & a = allocator_type(); //stored 112
+ Container c(a); //should propagate 112
+ BOOST_TEST (c.get_stored_allocator().id_ == 112);
+ BOOST_TEST (c.get_stored_allocator().ctr_copies_ > 0);
+ BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //copy allocator constructor
+ StoredAllocator::reset_unique_id(999);
+ Container c;
+ //stored_allocator_type could be the same type as allocator_type
+ //so reset it again to get a predictable result
+ allocator_type::reset_unique_id(222);
+ Container c2(c, allocator_type()); //should propagate 223
+ BOOST_TEST (c2.get_stored_allocator().id_ == 223);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+ {
+ //move allocator constructor
+ StoredAllocator::reset_unique_id(999);
+ Container c;
+ //stored_allocator_type could be the same type as allocator_type
+ //so reset it again to get a predictable result
+ allocator_type::reset_unique_id(333);
+ Container c2(boost::move(c), allocator_type()); //should propagate 334
+ BOOST_TEST (c2.get_stored_allocator().id_ == 334);
+ BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
+ BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+ BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+ }
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
diff --git a/src/boost/libs/container/test/propagation_test_allocator.hpp b/src/boost/libs/container/test/propagation_test_allocator.hpp
new file mode 100644
index 000000000..7c8643c55
--- /dev/null
+++ b/src/boost/libs/container/test/propagation_test_allocator.hpp
@@ -0,0 +1,268 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+
+#include <boost/container/uses_allocator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/core.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+
+template<class T, unsigned int Id, bool HasTrueTypes = false>
+class propagation_test_allocator
+{
+ BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+ public:
+
+ template<class U>
+ struct rebind
+ {
+ typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
+ };
+
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_move_assignment;
+ typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_swap;
+ typedef boost::container::dtl::bool_<HasTrueTypes> is_always_equal;
+ typedef T value_type;
+
+ propagation_test_allocator()
+ : m_default_contructed(true), m_move_contructed(false), m_move_assigned(false)
+ {}
+
+ propagation_test_allocator(const propagation_test_allocator&)
+ : m_default_contructed(false), m_move_contructed(false), m_move_assigned(false)
+ {}
+
+ propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
+ : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
+ {}
+
+ template<class U>
+ propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
+ : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
+ {}
+
+ template<class U>
+ propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
+ {}
+
+ propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
+ { return *this; }
+
+ propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
+ {
+ m_move_assigned = true;
+ return *this;
+ }
+
+ std::size_t max_size() const
+ { return std::size_t(-1); }
+
+ T* allocate(std::size_t n)
+ { return (T*)::new char[n*sizeof(T)]; }
+
+ void deallocate(T*p, std::size_t)
+ { delete []static_cast<char*>(static_cast<void*>(p)); }
+
+ bool m_default_contructed;
+ bool m_move_contructed;
+ bool m_move_assigned;
+};
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+ , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{ return true; }
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+ , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{ return false; }
+
+//This enum lists the construction options
+//for an allocator-aware type
+enum ConstructionTypeEnum
+{
+ ConstructiblePrefix,
+ ConstructibleSuffix,
+ ErasedTypePrefix,
+ ErasedTypeSuffix,
+ NotUsesAllocator
+};
+
+//This base class provices types for
+//the derived class to implement each construction
+//type. If a construction type does not apply
+//the typedef is set to an internal nat
+//so that the class is not constructible from
+//the user arguments.
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct uses_allocator_base;
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
+{
+ typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+ typedef allocator_type allocator_constructor_type;
+ struct nat{};
+ typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
+{
+ typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+ typedef allocator_type allocator_constructor_type;
+ typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ErasedTypePrefix, AllocatorTag>
+{
+ typedef boost::container::erased_type allocator_type;
+ typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
+ typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ErasedTypeSuffix, AllocatorTag>
+{
+ typedef boost::container::erased_type allocator_type;
+ typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
+ struct nat{};
+ typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
+{
+ struct nat{};
+ typedef nat allocator_constructor_type;
+ typedef nat allocator_arg_type;
+};
+
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct allocator_argument_tester
+ : uses_allocator_base<ConstructionType, AllocatorTag>
+{
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
+
+ public:
+
+ typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
+
+ //0 user argument constructors
+ allocator_argument_tester()
+ : construction_type(NotUsesAllocator), value(0)
+ {}
+
+ explicit allocator_argument_tester
+ (typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(0)
+ {}
+
+ explicit allocator_argument_tester
+ (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
+ : construction_type(ConstructiblePrefix), value(0)
+ {}
+
+ //1 user argument constructors
+ explicit allocator_argument_tester(int i)
+ : construction_type(NotUsesAllocator), value(i)
+ {}
+
+ allocator_argument_tester
+ (int i, typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(i)
+ {}
+
+ allocator_argument_tester
+ ( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , int i)
+ : construction_type(ConstructiblePrefix), value(i)
+ {}
+
+ //Copy constructors
+ allocator_argument_tester(const allocator_argument_tester &other)
+ : construction_type(NotUsesAllocator), value(other.value)
+ {}
+
+ allocator_argument_tester( const allocator_argument_tester &other
+ , typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(other.value)
+ {}
+
+ allocator_argument_tester( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , const allocator_argument_tester &other)
+ : construction_type(ConstructiblePrefix), value(other.value)
+ {}
+
+ //Move constructors
+ allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
+ : construction_type(NotUsesAllocator), value(other.value)
+ { other.value = 0; other.construction_type = NotUsesAllocator; }
+
+ allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
+ , typename base_type::allocator_constructor_type)
+ : construction_type(ConstructibleSuffix), value(other.value)
+ { other.value = 0; other.construction_type = ConstructibleSuffix; }
+
+ allocator_argument_tester( typename base_type::allocator_arg_type
+ , typename base_type::allocator_constructor_type
+ , BOOST_RV_REF(allocator_argument_tester) other)
+ : construction_type(ConstructiblePrefix), value(other.value)
+ { other.value = 0; other.construction_type = ConstructiblePrefix; }
+
+ ConstructionTypeEnum construction_type;
+ int value;
+};
+
+namespace boost {
+namespace container {
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+ < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+ < ::allocator_argument_tester<ErasedTypePrefix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+ < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+ < ::allocator_argument_tester<ErasedTypeSuffix, AllocatorTag> >
+{
+ static const bool value = true;
+};
+
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
diff --git a/src/boost/libs/container/test/resource_adaptor_test.cpp b/src/boost/libs/container/test/resource_adaptor_test.cpp
new file mode 100644
index 000000000..5f8ece297
--- /dev/null
+++ b/src/boost/libs/container/test/resource_adaptor_test.cpp
@@ -0,0 +1,234 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/resource_adaptor.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "propagation_test_allocator.hpp"
+#include "derived_from_memory_resource.hpp"
+#include <boost/container/new_allocator.hpp>
+#include <memory>
+
+using namespace boost::container::pmr;
+
+static const std::size_t max_alignment_value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+
+void test_default_constructor()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ resource_adaptor<alloc_t> ra;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+}
+
+void test_copy_constructor()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ resource_adaptor<alloc_t> ra;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ resource_adaptor<alloc_t> rb(ra);
+ BOOST_TEST(rb.get_allocator().m_default_contructed == false);
+ BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+}
+
+void test_move_constructor()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ resource_adaptor<alloc_t> ra;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ resource_adaptor<alloc_t> rb(::boost::move(ra));
+ BOOST_TEST(rb.get_allocator().m_default_contructed == false);
+ BOOST_TEST(rb.get_allocator().m_move_contructed == true);
+}
+
+void test_lvalue_alloc_constructor()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ alloc_t a;
+ resource_adaptor<alloc_t> ra(a);
+ BOOST_TEST(ra.get_allocator().m_default_contructed == false);
+ BOOST_TEST(ra.get_allocator().m_move_contructed == false);
+}
+
+void test_rvalue_alloc_constructor()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ alloc_t a;
+ resource_adaptor<alloc_t> ra(::boost::move(a));
+ BOOST_TEST(ra.get_allocator().m_default_contructed == false);
+ BOOST_TEST(ra.get_allocator().m_move_contructed == true);
+}
+
+void test_copy_assign()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ resource_adaptor<alloc_t> ra;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ resource_adaptor<alloc_t> rb;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ rb = ra;
+ BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+ BOOST_TEST(rb.get_allocator().m_move_assigned == false);
+}
+
+void test_move_assign()
+{
+ typedef propagation_test_allocator<char, 0> alloc_t;
+ resource_adaptor<alloc_t> ra;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ resource_adaptor<alloc_t> rb;
+ BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+ rb = ::boost::move(ra);
+ BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+ BOOST_TEST(rb.get_allocator().m_move_assigned == true);
+}
+
+struct stateful
+{
+ public:
+ typedef char value_type;
+
+ template<class U>
+ struct rebind
+ { typedef stateful other; };
+
+ stateful()
+ : m_u(0u)
+ {}
+
+ char *allocate(std::size_t n)
+ { allocate_size = n; return allocate_return; }
+
+ void deallocate(char *p, std::size_t n)
+ { deallocate_p = p; deallocate_size = n; }
+
+ friend bool operator==(const stateful &l, const stateful &r)
+ { return l.m_u == r.m_u; }
+
+ friend bool operator!=(const stateful &l, const stateful &r)
+ { return l.m_u != r.m_u; }
+
+ public:
+ unsigned m_u;
+ std::size_t allocate_size;
+ char *allocate_return;
+ std::size_t deallocate_size;
+ char *deallocate_p;
+};
+
+void test_get_allocator()
+{
+ stateful a;
+ a.m_u = 999;
+ resource_adaptor<stateful> ra(a);
+ const resource_adaptor<stateful> & cra = ra;
+ BOOST_TEST( ra.get_allocator().m_u == 999);
+ BOOST_TEST(cra.get_allocator().m_u == 999);
+}
+
+typedef resource_adaptor<stateful> stateful_resource_adaptor_t;
+
+struct derived_from_resource_adaptor_stateful
+ : public stateful_resource_adaptor_t
+{
+ public:
+ typedef stateful_resource_adaptor_t base_t;
+ using base_t::do_allocate;
+ using base_t::do_deallocate;
+ using base_t::do_is_equal;
+};
+
+void test_do_allocate_deallocate()
+{
+ {
+ derived_from_resource_adaptor_stateful dra;
+ char dummy = 0;
+ dra.get_allocator().allocate_return = &dummy;
+ void *allocate_ret = dra.do_allocate(998, 1);
+ BOOST_TEST(allocate_ret == &dummy);
+ BOOST_TEST(dra.get_allocator().allocate_size == 998);
+ }
+ {
+ derived_from_resource_adaptor_stateful dra;
+ char dummy = 0;
+ dra.do_deallocate(&dummy, 1234, 1);
+ BOOST_TEST(dra.get_allocator().deallocate_p == &dummy);
+ BOOST_TEST(dra.get_allocator().deallocate_size == 1234);
+ }
+ {
+ //Overaligned allocation
+ derived_from_resource_adaptor_stateful dra;
+ const std::size_t alignment = max_alignment_value*2u;
+ const std::size_t bytes = alignment/2;
+ char dummy[alignment*2u+sizeof(void*)];
+ dra.get_allocator().allocate_return = dummy;
+
+ //First allocate
+ void *allocate_ret = dra.do_allocate(bytes, alignment);
+ BOOST_TEST( (char*)allocate_ret >= (dummy+sizeof(void*)) && (char*)allocate_ret < (dummy + sizeof(dummy)) );
+ BOOST_TEST( (std::size_t(allocate_ret) & (alignment - 1u)) == 0 );
+ BOOST_TEST( dra.get_allocator().allocate_size >= (alignment/2+sizeof(void*)) );
+
+ //Then allocate
+ dra.do_deallocate(allocate_ret, bytes, alignment);
+ BOOST_TEST(dra.get_allocator().deallocate_p == dummy);
+ BOOST_TEST(dra.get_allocator().deallocate_size == dra.get_allocator().allocate_size);
+ }
+ {
+ typedef resource_adaptor< boost::container::new_allocator<int> > new_resource_alloc_t;
+ new_resource_alloc_t ra;
+ boost::container::pmr::memory_resource &mr = ra;
+
+ //new_allocator, low alignment
+ mr.deallocate(mr.allocate(16, 1), 16, 1);
+
+ //new_allocator, high alignment
+ mr.deallocate(mr.allocate(16, max_alignment_value*4u), 16, max_alignment_value*4u);
+ }
+ {
+ typedef resource_adaptor<std ::allocator<int> > new_resource_alloc_t;
+ new_resource_alloc_t ra;
+ boost::container::pmr::memory_resource &mr = ra;
+
+ //std::allocator, low alignment
+ mr.deallocate(mr.allocate(16, 1), 16, 1);
+
+ //std::allocator, high alignment
+ mr.deallocate(mr.allocate(16, max_alignment_value*4u), 16, max_alignment_value*4u);
+ }
+}
+
+void test_do_is_equal()
+{
+ derived_from_resource_adaptor_stateful dra;
+ derived_from_memory_resource dmr;
+ //Different dynamic type must return false
+ BOOST_TEST(dra.do_is_equal(dmr) == false);
+
+ //Same dynamic type with same state must return true
+ derived_from_resource_adaptor_stateful dra2;
+ BOOST_TEST(dra.do_is_equal(dra2) == true);
+
+ //Same dynamic type with different state must return false
+ dra2.get_allocator().m_u = 1234;
+ BOOST_TEST(dra.do_is_equal(dra2) == false);
+}
+
+int main()
+{
+ test_default_constructor();
+ test_copy_constructor();
+ test_move_constructor();
+ test_lvalue_alloc_constructor();
+ test_rvalue_alloc_constructor();
+ test_copy_assign();
+ test_move_assign();
+ test_get_allocator();
+ test_do_allocate_deallocate();
+ test_do_is_equal();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp b/src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp
new file mode 100644
index 000000000..6a051e279
--- /dev/null
+++ b/src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp
@@ -0,0 +1,1377 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/scoped_allocator_fwd.hpp>
+
+// container/detail
+#include <boost/container/detail/mpl.hpp>
+// move
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+//boost
+#include <boost/tuple/tuple.hpp>
+// std
+#include <memory>
+#include <cstddef>
+
+#if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+#include <tuple>
+#endif
+
+//test
+#include <boost/core/lightweight_test.hpp>
+
+#include "allocator_argument_tester.hpp"
+
+template<unsigned int Type>
+struct tagged_integer
+{};
+
+struct mark_on_destructor
+{
+ mark_on_destructor()
+ {
+ destroyed = false;
+ }
+
+ ~mark_on_destructor()
+ {
+ destroyed = true;
+ }
+
+ static bool destroyed;
+};
+
+bool mark_on_destructor::destroyed = false;
+
+#include <boost/container/scoped_allocator.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/detail/pair.hpp>
+
+int main()
+{
+ using namespace boost::container;
+
+ typedef propagation_test_allocator<tagged_integer<0>, 0> OuterAlloc;
+ typedef propagation_test_allocator<tagged_integer<0>, 10> Outer10IdAlloc;
+ typedef propagation_test_allocator<tagged_integer<9>, 0> Rebound9OuterAlloc;
+ typedef propagation_test_allocator<tagged_integer<1>, 1> InnerAlloc1;
+ typedef propagation_test_allocator<tagged_integer<2>, 2> InnerAlloc2;
+ typedef propagation_test_allocator<tagged_integer<1>, 11> Inner11IdAlloc1;
+
+ typedef propagation_test_allocator<tagged_integer<0>, 0, false> OuterAllocFalseHasTrueTypes;
+ typedef propagation_test_allocator<tagged_integer<0>, 0, true> OuterAllocTrueHasTrueTypes;
+ typedef propagation_test_allocator<tagged_integer<1>, 1, false> InnerAlloc1FalseHasTrueTypes;
+ typedef propagation_test_allocator<tagged_integer<1>, 1, true> InnerAlloc1TrueHasTrueTypes;
+ typedef propagation_test_allocator<tagged_integer<2>, 2, false> InnerAlloc2FalseHasTrueTypes;
+ typedef propagation_test_allocator<tagged_integer<2>, 2, true> InnerAlloc2TrueHasTrueTypes;
+
+ //
+ typedef scoped_allocator_adaptor< OuterAlloc > Scoped0Inner;
+ typedef scoped_allocator_adaptor< OuterAlloc
+ , InnerAlloc1 > Scoped1Inner;
+ typedef scoped_allocator_adaptor< OuterAlloc
+ , InnerAlloc1
+ , InnerAlloc2 > Scoped2Inner;
+ typedef scoped_allocator_adaptor
+ < scoped_allocator_adaptor
+ <Outer10IdAlloc>
+ > ScopedScoped0Inner;
+ typedef scoped_allocator_adaptor
+ < scoped_allocator_adaptor
+ <Outer10IdAlloc, Inner11IdAlloc1>
+ , InnerAlloc1
+ > ScopedScoped1Inner;
+ typedef scoped_allocator_adaptor< Rebound9OuterAlloc > Rebound9Scoped0Inner;
+ typedef scoped_allocator_adaptor< Rebound9OuterAlloc
+ , InnerAlloc1 > Rebound9Scoped1Inner;
+ typedef scoped_allocator_adaptor< Rebound9OuterAlloc
+ , InnerAlloc1
+ , InnerAlloc2 > Rebound9Scoped2Inner;
+
+ //outer_allocator_type
+ BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+ , Scoped0Inner::outer_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+ , Scoped1Inner::outer_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+ , Scoped2Inner::outer_allocator_type>::value ));
+ //value_type
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+ , Scoped0Inner::value_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+ , Scoped1Inner::value_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+ , Scoped2Inner::value_type>::value ));
+ //size_type
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+ , Scoped0Inner::size_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+ , Scoped1Inner::size_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+ , Scoped2Inner::size_type>::value ));
+
+ //difference_type
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+ , Scoped0Inner::difference_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+ , Scoped1Inner::difference_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+ , Scoped2Inner::difference_type>::value ));
+
+ //pointer
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+ , Scoped0Inner::pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+ , Scoped1Inner::pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+ , Scoped2Inner::pointer>::value ));
+
+ //const_pointer
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+ , Scoped0Inner::const_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+ , Scoped1Inner::const_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+ , Scoped2Inner::const_pointer>::value ));
+
+ //void_pointer
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+ , Scoped0Inner::void_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+ , Scoped1Inner::void_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+ , Scoped2Inner::void_pointer>::value ));
+
+ //const_void_pointer
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+ , Scoped0Inner::const_void_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+ , Scoped1Inner::const_void_pointer>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+ , Scoped2Inner::const_void_pointer>::value ));
+
+ //rebind
+ BOOST_STATIC_ASSERT(( dtl::is_same<Scoped0Inner::rebind< tagged_integer<9> >::other
+ , Rebound9Scoped0Inner >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<Scoped1Inner::rebind< tagged_integer<9> >::other
+ , Rebound9Scoped1Inner >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same<Scoped2Inner::rebind< tagged_integer<9> >::other
+ , Rebound9Scoped2Inner >::value ));
+
+ //inner_allocator_type
+ BOOST_STATIC_ASSERT(( dtl::is_same< Scoped0Inner
+ , Scoped0Inner::inner_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< scoped_allocator_adaptor<InnerAlloc1>
+ , Scoped1Inner::inner_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same< scoped_allocator_adaptor<InnerAlloc1, InnerAlloc2>
+ , Scoped2Inner::inner_allocator_type>::value ));
+
+ {
+ //Propagation test
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes > Scoped0InnerF;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes > Scoped0InnerT;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes > Scoped1InnerFF;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes > Scoped1InnerFT;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes > Scoped1InnerTF;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes > Scoped1InnerTT;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes
+ , InnerAlloc2FalseHasTrueTypes > Scoped2InnerFFF;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes
+ , InnerAlloc2TrueHasTrueTypes > Scoped2InnerFFT;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes
+ , InnerAlloc2FalseHasTrueTypes > Scoped2InnerFTF;
+ typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes
+ , InnerAlloc2TrueHasTrueTypes > Scoped2InnerFTT;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes
+ , InnerAlloc2FalseHasTrueTypes > Scoped2InnerTFF;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1FalseHasTrueTypes
+ , InnerAlloc2TrueHasTrueTypes > Scoped2InnerTFT;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes
+ , InnerAlloc2FalseHasTrueTypes > Scoped2InnerTTF;
+ typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+ , InnerAlloc1TrueHasTrueTypes
+ , InnerAlloc2TrueHasTrueTypes > Scoped2InnerTTT;
+
+ //propagate_on_container_copy_assignment
+ //0 inner
+ BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_copy_assignment::value ));
+ //1 inner
+ BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_copy_assignment::value ));
+ //2 inner
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_copy_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_copy_assignment::value ));
+
+ //propagate_on_container_move_assignment
+ //0 inner
+ BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_move_assignment::value ));
+ //1 inner
+ BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_move_assignment::value ));
+ //2 inner
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_move_assignment::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_move_assignment::value ));
+
+ //propagate_on_container_swap
+ //0 inner
+ BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_swap::value ));
+ //1 inner
+ BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_swap::value ));
+ //2 inner
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_swap::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_swap::value ));
+ //is_always_equal
+ //0 inner
+ BOOST_STATIC_ASSERT(( !Scoped0InnerF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( Scoped0InnerT::is_always_equal::value ));
+ //1 inner
+ BOOST_STATIC_ASSERT(( !Scoped1InnerFF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped1InnerFT::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped1InnerTF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( Scoped1InnerTT::is_always_equal::value ));
+ //2 inner
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFFT::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFTF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerFTT::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerTFF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerTFT::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( !Scoped2InnerTTF::is_always_equal::value ));
+ BOOST_STATIC_ASSERT(( Scoped2InnerTTT::is_always_equal::value ));
+ }
+
+ //Default constructor
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ //Swap
+ {
+ Scoped0Inner s0i2;
+ Scoped1Inner s1i2;
+ boost::adl_move_swap(s0i, s0i2);
+ boost::adl_move_swap(s1i, s1i2);
+ }
+ }
+
+ //Default constructor
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ }
+
+ //Copy constructor/assignment
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ Scoped2Inner s2i;
+
+ Scoped0Inner s0i_b(s0i);
+ Scoped1Inner s1i_b(s1i);
+ Scoped2Inner s2i_b(s2i);
+
+ BOOST_TEST(s0i == s0i_b);
+ BOOST_TEST(s1i == s1i_b);
+ BOOST_TEST(s2i == s2i_b);
+
+ s0i_b = s0i;
+ s1i_b = s1i;
+ s2i_b = s2i;
+
+ BOOST_TEST(s0i == s0i_b);
+ BOOST_TEST(s1i == s1i_b);
+ BOOST_TEST(s2i == s2i_b);
+ }
+
+ //Copy/move constructor/assignment
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ Scoped2Inner s2i;
+
+ Scoped0Inner s0i_b(::boost::move(s0i));
+ Scoped1Inner s1i_b(::boost::move(s1i));
+ Scoped2Inner s2i_b(::boost::move(s2i));
+
+ BOOST_TEST(s0i_b.outer_allocator().m_move_contructed);
+ BOOST_TEST(s1i_b.outer_allocator().m_move_contructed);
+ BOOST_TEST(s2i_b.outer_allocator().m_move_contructed);
+
+ s0i_b = ::boost::move(s0i);
+ s1i_b = ::boost::move(s1i);
+ s2i_b = ::boost::move(s2i);
+
+ BOOST_TEST(s0i_b.outer_allocator().m_move_assigned);
+ BOOST_TEST(s1i_b.outer_allocator().m_move_assigned);
+ BOOST_TEST(s2i_b.outer_allocator().m_move_assigned);
+ }
+
+ //inner_allocator()
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ Scoped2Inner s2i;
+ const Scoped0Inner const_s0i;
+ const Scoped1Inner const_s1i;
+ const Scoped2Inner const_s2i;
+
+ Scoped0Inner::inner_allocator_type &s0i_inner = s0i.inner_allocator();
+ (void)s0i_inner;
+ const Scoped0Inner::inner_allocator_type &const_s0i_inner = const_s0i.inner_allocator();
+ (void)const_s0i_inner;
+ Scoped1Inner::inner_allocator_type &s1i_inner = s1i.inner_allocator();
+ (void)s1i_inner;
+ const Scoped1Inner::inner_allocator_type &const_s1i_inner = const_s1i.inner_allocator();
+ (void)const_s1i_inner;
+ Scoped2Inner::inner_allocator_type &s2i_inner = s2i.inner_allocator();
+ (void)s2i_inner;
+ const Scoped2Inner::inner_allocator_type &const_s2i_inner = const_s2i.inner_allocator();
+ (void)const_s2i_inner;
+ }
+
+ //operator==/!=
+ {
+ const Scoped0Inner const_s0i;
+ const Rebound9Scoped0Inner const_rs0i;
+
+ BOOST_TEST(const_s0i == const_s0i);
+ BOOST_TEST(const_rs0i == const_s0i);
+ BOOST_TEST(const_s0i == const_s0i);
+ BOOST_TEST(const_s0i == const_rs0i);
+
+ const Scoped1Inner const_s1i;
+ const Rebound9Scoped1Inner const_rs1i;
+
+ BOOST_TEST(const_s1i == const_s1i);
+ BOOST_TEST(const_rs1i == const_s1i);
+
+ BOOST_TEST(const_s1i == const_s1i);
+ BOOST_TEST(const_s1i == const_rs1i);
+
+ const Scoped2Inner const_s2i;
+ const Rebound9Scoped2Inner const_rs2i;
+
+ BOOST_TEST(const_s2i == const_s2i);
+ BOOST_TEST(const_s2i == const_rs2i);
+
+ BOOST_TEST(const_s2i == const_s2i);
+ BOOST_TEST(const_s2i == const_rs2i);
+ }
+
+ //outer_allocator()
+ {
+ Scoped0Inner s0i;
+ Scoped1Inner s1i;
+ Scoped2Inner s2i;
+ const Scoped0Inner const_s0i;
+ const Scoped1Inner const_s1i;
+ const Scoped2Inner const_s2i;
+
+ Scoped0Inner::outer_allocator_type &s0i_inner = s0i.outer_allocator();
+ (void)s0i_inner;
+ const Scoped0Inner::outer_allocator_type &const_s0i_inner = const_s0i.outer_allocator();
+ (void)const_s0i_inner;
+ Scoped1Inner::outer_allocator_type &s1i_inner = s1i.outer_allocator();
+ (void)s1i_inner;
+ const Scoped1Inner::outer_allocator_type &const_s1i_inner = const_s1i.outer_allocator();
+ (void)const_s1i_inner;
+ Scoped2Inner::outer_allocator_type &s2i_inner = s2i.outer_allocator();
+ (void)s2i_inner;
+ const Scoped2Inner::outer_allocator_type &const_s2i_inner = const_s2i.outer_allocator();
+ (void)const_s2i_inner;
+ }
+
+ //max_size()
+ {
+ const Scoped0Inner const_s0i;
+ const Scoped1Inner const_s1i;
+ const Scoped2Inner const_s2i;
+ const OuterAlloc const_oa;
+ const InnerAlloc1 const_ia1;
+ const InnerAlloc2 const_ia2;
+
+ BOOST_TEST(const_s0i.max_size() == const_oa.max_size());
+ BOOST_TEST(const_s1i.max_size() == const_oa.max_size());
+
+ BOOST_TEST(const_s2i.max_size() == const_oa.max_size());
+ BOOST_TEST(const_s1i.inner_allocator().max_size() == const_ia1.max_size());
+ BOOST_TEST(const_s2i.inner_allocator().inner_allocator().max_size() == const_ia2.max_size());
+ }
+ //Copy and move operations
+ {
+ //Construction
+ {
+ Scoped0Inner s0i_a, s0i_b(s0i_a), s0i_c(::boost::move(s0i_b));
+ Scoped1Inner s1i_a, s1i_b(s1i_a), s1i_c(::boost::move(s1i_b));
+ Scoped2Inner s2i_a, s2i_b(s2i_a), s2i_c(::boost::move(s2i_b));
+ }
+ //Assignment
+ {
+ Scoped0Inner s0i_a, s0i_b;
+ s0i_a = s0i_b;
+ s0i_a = ::boost::move(s0i_b);
+ Scoped1Inner s1i_a, s1i_b;
+ s1i_a = s1i_b;
+ s1i_a = ::boost::move(s1i_b);
+ Scoped2Inner s2i_a, s2i_b;
+ s2i_a = s2i_b;
+ s2i_a = ::boost::move(s2i_b);
+ }
+
+ OuterAlloc oa;
+ InnerAlloc1 ia1;
+ InnerAlloc2 ia2;
+ Rebound9OuterAlloc roa;
+ Rebound9Scoped0Inner rs0i;
+ Rebound9Scoped1Inner rs1i;
+ Rebound9Scoped2Inner rs2i;
+
+ //Copy from outer
+ {
+ Scoped0Inner s0i(oa);
+ Scoped1Inner s1i(oa, ia1);
+ Scoped2Inner s2i(oa, ia1, ia2);
+ }
+ //Move from outer
+ {
+ Scoped0Inner s0i(::boost::move(oa));
+ Scoped1Inner s1i(::boost::move(oa), ia1);
+ Scoped2Inner s2i(::boost::move(oa), ia1, ia2);
+ }
+ //Copy from rebound outer
+ {
+ Scoped0Inner s0i(roa);
+ Scoped1Inner s1i(roa, ia1);
+ Scoped2Inner s2i(roa, ia1, ia2);
+ }
+ //Move from rebound outer
+ {
+ Scoped0Inner s0i(::boost::move(roa));
+ Scoped1Inner s1i(::boost::move(roa), ia1);
+ Scoped2Inner s2i(::boost::move(roa), ia1, ia2);
+ }
+ //Copy from rebound scoped
+ {
+ Scoped0Inner s0i(rs0i);
+ Scoped1Inner s1i(rs1i);
+ Scoped2Inner s2i(rs2i);
+ }
+ //Move from rebound scoped
+ {
+ Scoped0Inner s0i(::boost::move(rs0i));
+ Scoped1Inner s1i(::boost::move(rs1i));
+ Scoped2Inner s2i(::boost::move(rs2i));
+ }
+ }
+
+ {
+ vector<int, scoped_allocator_adaptor< propagation_test_allocator<int, 0> > > dummy;
+ dummy.push_back(0);
+ }
+
+ //destroy()
+ {
+ {
+ Scoped0Inner s0i;
+ mark_on_destructor mod;
+ s0i.destroy(&mod);
+ BOOST_TEST(mark_on_destructor::destroyed);
+ }
+
+ {
+ Scoped1Inner s1i;
+ mark_on_destructor mod;
+ s1i.destroy(&mod);
+ BOOST_TEST(mark_on_destructor::destroyed);
+ }
+ {
+ Scoped2Inner s2i;
+ mark_on_destructor mod;
+ s2i.destroy(&mod);
+ BOOST_TEST(mark_on_destructor::destroyed);
+ }
+ }
+
+ //construct
+ {
+ ////////////////////////////////////////////////////////////
+ //First check scoped allocator with just OuterAlloc.
+ //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+ //used to construct types.
+ ////////////////////////////////////////////////////////////
+ {
+ Scoped0Inner s0i;
+ //Check construction with 0 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0 );
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+
+ //Check construction with 1 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy, 1);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 1);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy, 2);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 2);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s0i.construct(&dummy, 3);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 3);
+ dummy.~MarkType();
+ }
+ }
+ ////////////////////////////////////////////////////////////
+ //Then check scoped allocator with OuterAlloc and InnerAlloc.
+ //In this case InnerAlloc (propagation_test_allocator with tag 1) should be
+ //used to construct types.
+ ////////////////////////////////////////////////////////////
+ {
+ Scoped1Inner s1i;
+ //Check construction with 0 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+
+ //Check construction with 1 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy, 1);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 1);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy, 2);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 2);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ s1i.construct(&dummy, 3);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 3);
+ dummy.~MarkType();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ //Now test recursive OuterAllocator types (OuterAllocator is a scoped_allocator)
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////
+ //First check scoped allocator with just OuterAlloc.
+ //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+ //used to construct types.
+ ////////////////////////////////////////////////////////////
+ {
+ //Check outer_allocator_type is scoped
+ BOOST_STATIC_ASSERT(( is_scoped_allocator
+ <ScopedScoped0Inner::outer_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < outermost_allocator<ScopedScoped0Inner>::type
+ , Outer10IdAlloc
+ >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < ScopedScoped0Inner::outer_allocator_type
+ , scoped_allocator_adaptor<Outer10IdAlloc>
+ >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < scoped_allocator_adaptor<Outer10IdAlloc>::outer_allocator_type
+ , Outer10IdAlloc
+ >::value ));
+ ScopedScoped0Inner ssro0i;
+ Outer10IdAlloc & val = outermost_allocator<ScopedScoped0Inner>::get(ssro0i);
+ (void)val;
+ //Check construction with 0 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+
+ //Check construction with 1 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy, 1);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 1);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy, 2);
+ BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.value == 2);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro0i.construct(&dummy, 3);
+ BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.value == 3);
+ dummy.~MarkType();
+ }
+ }
+ ////////////////////////////////////////////////////////////
+ //Then check scoped allocator with OuterAlloc and InnerAlloc.
+ //In this case inner_allocator_type is not convertible to
+ //::allocator_argument_tester<XXX, 10> so uses_allocator
+ //should be false on all tests.
+ ////////////////////////////////////////////////////////////
+ {
+ //Check outer_allocator_type is scoped
+ BOOST_STATIC_ASSERT(( is_scoped_allocator
+ <ScopedScoped1Inner::outer_allocator_type>::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < outermost_allocator<ScopedScoped1Inner>::type
+ , Outer10IdAlloc
+ >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < ScopedScoped1Inner::outer_allocator_type
+ , scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>
+ >::value ));
+ BOOST_STATIC_ASSERT(( dtl::is_same
+ < scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>::outer_allocator_type
+ , Outer10IdAlloc
+ >::value ));
+ BOOST_STATIC_ASSERT(( !
+ uses_allocator
+ < ::allocator_argument_tester<ConstructibleSuffix, 10>
+ , ScopedScoped1Inner::inner_allocator_type::outer_allocator_type
+ >::value ));
+ ScopedScoped1Inner ssro1i;
+ Outer10IdAlloc & val = outermost_allocator<ScopedScoped1Inner>::get(ssro1i);
+ (void)val;
+
+ //Check construction with 0 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 0);
+ dummy.~MarkType();
+ }
+
+ //Check construction with 1 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy, 1);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 1);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy, 2);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 2);
+ dummy.~MarkType();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+ MarkType dummy;
+ dummy.~MarkType();
+ ssro1i.construct(&dummy, 3);
+ BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.value == 3);
+ dummy.~MarkType();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////
+ //Now check propagation to pair
+ ////////////////////////////////////////////////////////////
+ //First check scoped allocator with just OuterAlloc.
+ //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+ //used to construct types.
+ ////////////////////////////////////////////////////////////
+ {
+ using dtl::pair;
+ typedef propagation_test_allocator< pair< tagged_integer<0>
+ , tagged_integer<0> >, 0> OuterPairAlloc;
+ //
+ typedef scoped_allocator_adaptor < OuterPairAlloc > ScopedPair0Inner;
+
+ ScopedPair0Inner s0i;
+ //Check construction with 0 user arguments
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy);
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+ //Check construction with 0 user arguments and Std tuple
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+ //Check construction with 1 user arguments for each pair
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, 1, 1);
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, 1, 1);
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, 2, 2);
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ //Check construction with 1 user arguments for each pair and Boost tuple
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(2), boost::tuple<int>(2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+ //Check construction with 1 user arguments for each pair and Boost tuple
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<int>(2), std::tuple<int>(2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+ //Check construction with pair copy construction
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2(1, 1);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2(2, 2);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ //Check construction with pair move construction
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2(3, 3);
+ dummy2.first.construction_type = dummy2.second.construction_type = ConstructibleSuffix;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 3);
+ BOOST_TEST(dummy.second.value == 3);
+ BOOST_TEST(dummy2.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy2.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy2.first.value == 0);
+ BOOST_TEST(dummy2.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2(1, 1);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ BOOST_TEST(dummy2.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy2.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy2.first.value == 0);
+ BOOST_TEST(dummy2.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy, dummy2(2, 2);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ BOOST_TEST(dummy2.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy2.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy2.first.value == 0);
+ BOOST_TEST(dummy2.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ //Check construction with related pair copy construction
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2(1, 1);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2(2, 2);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, dummy2);
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ //Check construction with related pair move construction
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2(3, 3);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 3);
+ BOOST_TEST(dummy.second.value == 3);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2(1, 1);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ pair<int, int> dummy2(2, 2);
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, ::boost::move(dummy2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 2);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ //Check construction with 0/1 arguments for each pair and Boost tuple
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple<int>(2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+ //Check construction with 0/1 arguments for each pair and Boost tuple
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<int>(1));
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<>());
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 1);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<int>(2));
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 0);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ #endif //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+
+ //Check construction with try_emplace_t 0/1 arguments for each pair
+ {
+ typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, try_emplace_t(), 5, 1);
+ BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+ BOOST_TEST(dummy.first.value == 5);
+ BOOST_TEST(dummy.second.value == 1);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, try_emplace_t(), 6);
+ BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+ BOOST_TEST(dummy.first.value == 6);
+ BOOST_TEST(dummy.second.value == 0);
+ dummy.~MarkTypePair();
+ }
+ {
+ typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+ typedef pair<MarkType, MarkType> MarkTypePair;
+ MarkTypePair dummy;
+ dummy.~MarkTypePair();
+ s0i.construct(&dummy, try_emplace_t(), 7, 2);
+ BOOST_TEST(dummy.first.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+ BOOST_TEST(dummy.first.value == 7);
+ BOOST_TEST(dummy.second.value == 2);
+ dummy.~MarkTypePair();
+ }
+ }
+ }
+
+ return ::boost::report_errors();
+}
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/scoped_allocator_usage_test.cpp b/src/boost/libs/container/test/scoped_allocator_usage_test.cpp
new file mode 100644
index 000000000..6eb143811
--- /dev/null
+++ b/src/boost/libs/container/test/scoped_allocator_usage_test.cpp
@@ -0,0 +1,428 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/set.hpp>
+#include <boost/container/detail/mpl.hpp>
+
+#include <boost/container/scoped_allocator.hpp>
+
+template <typename Ty>
+class SimpleAllocator
+{
+public:
+ typedef Ty value_type;
+
+ explicit SimpleAllocator(int value)
+ : m_state(value)
+ {}
+
+ template <typename T>
+ SimpleAllocator(const SimpleAllocator<T> &other)
+ : m_state(other.m_state)
+ {}
+
+ Ty* allocate(std::size_t n)
+ {
+ return m_allocator.allocate(n);
+ }
+
+ void deallocate(Ty* p, std::size_t n)
+ {
+ m_allocator.deallocate(p, n);
+ }
+
+ int get_value() const
+ { return m_state; }
+
+ private:
+ int m_state;
+ std::allocator<Ty> m_allocator;
+
+ template <typename T> friend class SimpleAllocator;
+
+ friend bool operator == (const SimpleAllocator &, const SimpleAllocator &)
+ { return true; }
+
+ friend bool operator != (const SimpleAllocator &, const SimpleAllocator &)
+ { return false; }
+};
+
+class alloc_int
+{
+ private: // Not copyable
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int)
+
+ public:
+ typedef SimpleAllocator<int> allocator_type;
+
+ alloc_int(BOOST_RV_REF(alloc_int)other)
+ : m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
+ {
+ other.m_value = -1;
+ }
+
+ alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator)
+ : m_value(other.m_value), m_allocator(allocator)
+ {
+ other.m_value = -1;
+ }
+
+ alloc_int(int value, const allocator_type &allocator)
+ : m_value(value), m_allocator(allocator)
+ {}
+
+ alloc_int & operator=(BOOST_RV_REF(alloc_int)other)
+ {
+ other.m_value = other.m_value;
+ return *this;
+ }
+
+ int get_allocator_state() const
+ { return m_allocator.get_value(); }
+
+ int get_value() const
+ { return m_value; }
+
+ friend bool operator < (const alloc_int &l, const alloc_int &r)
+ { return l.m_value < r.m_value; }
+
+ friend bool operator == (const alloc_int &l, const alloc_int &r)
+ { return l.m_value == r.m_value; }
+
+ private:
+ int m_value;
+ allocator_type m_allocator;
+};
+
+using namespace ::boost::container;
+
+//general allocator
+typedef scoped_allocator_adaptor<SimpleAllocator<alloc_int> > AllocIntAllocator;
+
+//[multi]map/set
+typedef std::pair<const alloc_int, alloc_int> MapNode;
+typedef scoped_allocator_adaptor<SimpleAllocator<MapNode> > MapAllocator;
+typedef map<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> Map;
+typedef set<alloc_int, std::less<alloc_int>, AllocIntAllocator> Set;
+typedef multimap<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> MultiMap;
+typedef multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> MultiSet;
+
+//[multi]flat_map/set
+typedef std::pair<alloc_int, alloc_int> FlatMapNode;
+typedef scoped_allocator_adaptor<SimpleAllocator<FlatMapNode> > FlatMapAllocator;
+typedef flat_map<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMap;
+typedef flat_set<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatSet;
+typedef flat_multimap<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMultiMap;
+typedef flat_multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatMultiSet;
+
+//vector, deque, list, slist, stable_vector.
+typedef vector<alloc_int, AllocIntAllocator> Vector;
+typedef deque<alloc_int, AllocIntAllocator> Deque;
+typedef list<alloc_int, AllocIntAllocator> List;
+typedef slist<alloc_int, AllocIntAllocator> Slist;
+typedef stable_vector<alloc_int, AllocIntAllocator> StableVector;
+typedef small_vector<alloc_int, 9, AllocIntAllocator> SmallVector;
+
+/////////
+//is_unique_assoc
+/////////
+
+template<class T>
+struct is_unique_assoc
+{
+ static const bool value = false;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_unique_assoc< map<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_unique_assoc< flat_map<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_unique_assoc< set<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_unique_assoc< flat_set<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+
+/////////
+//is_map
+/////////
+
+template<class T>
+struct is_map
+{
+ static const bool value = false;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< map<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< flat_map<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< multimap<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< flat_multimap<Key, T, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class T>
+struct is_set
+{
+ static const bool value = false;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< set<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< flat_set<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< multiset<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< flat_multiset<Key, Compare, Allocator> >
+{
+ static const bool value = true;
+};
+
+/////////
+//container_wrapper
+/////////
+
+//Try to define-allocator_aware requirements
+template< class Container
+ , bool Assoc = is_set<Container>::value || is_map<Container>::value
+ , bool UniqueAssoc = is_unique_assoc<Container>::value
+ , bool Map = is_map<Container>::value
+ >
+struct container_wrapper_inserter
+{
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ template<class Arg>
+ static iterator emplace(Container &c, const_iterator p, const Arg &arg)
+ { return c.emplace(p, arg); }
+};
+
+template<class Container> //map
+struct container_wrapper_inserter<Container, true, true, true>
+{
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ template<class Arg>
+ static iterator emplace(Container &c, const_iterator, const Arg &arg)
+ { return c.emplace(arg, arg).first; }
+};
+
+template<class Container> //set
+struct container_wrapper_inserter<Container, true, true, false>
+{
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ template<class Arg>
+ static iterator emplace(Container &c, const_iterator, const Arg &arg)
+ { return c.emplace(arg).first; }
+};
+
+template<class Container> //multimap
+struct container_wrapper_inserter<Container, true, false, true>
+{
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ template<class Arg>
+ static iterator emplace(Container &c, const_iterator, const Arg &arg)
+ { return c.emplace(arg, arg); }
+};
+
+//multiset
+template<class Container> //multimap
+struct container_wrapper_inserter<Container, true, false, false>
+{
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ template<class Arg>
+ static iterator emplace(Container &c, const_iterator, const Arg &arg)
+ { return c.emplace(arg); }
+};
+
+template< class Container>
+struct container_wrapper
+ : public Container
+{
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(container_wrapper)
+
+ public:
+ typedef typename Container::allocator_type allocator_type;
+ typedef typename Container::const_iterator const_iterator;
+ typedef typename Container::iterator iterator;
+
+ container_wrapper(const allocator_type &a)
+ : Container(a)
+ {}
+
+ container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a)
+ : Container(BOOST_MOVE_BASE(Container, o), a)
+ {}
+
+ container_wrapper(const container_wrapper &o, const allocator_type &a)
+ : Container(o, a)
+ {}
+
+ template<class Arg>
+ iterator emplace(const_iterator p, const Arg &arg)
+ { return container_wrapper_inserter<Container>::emplace(*this, p, arg); }
+};
+
+
+bool test_value_and_state_equals(const alloc_int &r, int value, int state)
+{ return r.get_value() == value && r.get_allocator_state() == state; }
+
+template<class F, class S>
+bool test_value_and_state_equals(const dtl::pair<F, S> &p, int value, int state)
+{ return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state); }
+
+template<class F, class S>
+bool test_value_and_state_equals(const std::pair<F, S> &p, int value, int state)
+{ return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state); }
+
+template<class Container>
+bool one_level_allocator_propagation_test()
+{
+ typedef container_wrapper<Container> ContainerWrapper;
+ typedef typename ContainerWrapper::iterator iterator;
+ typedef typename ContainerWrapper::allocator_type allocator_type;
+ typedef typename ContainerWrapper::value_type value_type;
+ {
+ allocator_type al(SimpleAllocator<value_type>(5));
+ ContainerWrapper c(al);
+
+ c.clear();
+ iterator it = c.emplace(c.cbegin(), 42);
+
+ if(!test_value_and_state_equals(*it, 42, 5))
+ return false;
+ }
+ {
+ allocator_type al(SimpleAllocator<value_type>(4));
+ ContainerWrapper c2(al);
+ ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator<value_type>(5)));
+
+ c.clear();
+ iterator it = c.emplace(c.cbegin(), 42);
+
+ if(!test_value_and_state_equals(*it, 42, 5))
+ return false;
+ }/*
+ {
+ ContainerWrapper c2(allocator_type(SimpleAllocator<value_type>(3)));
+ ContainerWrapper c(c2, allocator_type(SimpleAllocator<value_type>(5)));
+
+ c.clear();
+ iterator it = c.emplace(c.cbegin(), 42);
+
+ if(!test_value_and_state_equals(*it, 42, 5))
+ return false;
+ }*/
+ return true;
+}
+
+int main()
+{
+ //unique assoc
+ if(!one_level_allocator_propagation_test<FlatMap>())
+ return 1;
+ if(!one_level_allocator_propagation_test<Map>())
+ return 1;
+ if(!one_level_allocator_propagation_test<FlatSet>())
+ return 1;
+ if(!one_level_allocator_propagation_test<Set>())
+ return 1;
+ //multi assoc
+ if(!one_level_allocator_propagation_test<FlatMultiMap>())
+ return 1;
+ if(!one_level_allocator_propagation_test<MultiMap>())
+ return 1;
+ if(!one_level_allocator_propagation_test<FlatMultiSet>())
+ return 1;
+ if(!one_level_allocator_propagation_test<MultiSet>())
+ return 1;
+ //sequence containers
+ if(!one_level_allocator_propagation_test<Vector>())
+ return 1;
+ if(!one_level_allocator_propagation_test<Deque>())
+ return 1;
+ if(!one_level_allocator_propagation_test<List>())
+ return 1;
+ if(!one_level_allocator_propagation_test<Slist>())
+ return 1;
+ if(!one_level_allocator_propagation_test<StableVector>())
+ return 1;
+ if(!one_level_allocator_propagation_test<SmallVector>())
+ return 1;
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/set_test.cpp b/src/boost/libs/container/test/set_test.cpp
new file mode 100644
index 000000000..a7d0b4741
--- /dev/null
+++ b/src/boost/libs/container/test/set_test.cpp
@@ -0,0 +1,655 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <set>
+#include <boost/container/set.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include "set_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+//Test recursive structures
+class recursive_set
+{
+public:
+ recursive_set & operator=(const recursive_set &x)
+ { id_ = x.id_; set_ = x.set_; return *this; }
+
+ int id_;
+ set<recursive_set> set_;
+ set<recursive_set>::iterator it_;
+ set<recursive_set>::const_iterator cit_;
+ set<recursive_set>::reverse_iterator rit_;
+ set<recursive_set>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_set &a, const recursive_set &b)
+ { return a.id_ < b.id_; }
+};
+
+//Test recursive structures
+class recursive_multiset
+{
+ public:
+ recursive_multiset & operator=(const recursive_multiset &x)
+ { id_ = x.id_; multiset_ = x.multiset_; return *this; }
+
+ int id_;
+ multiset<recursive_multiset> multiset_;
+ multiset<recursive_multiset>::iterator it_;
+ multiset<recursive_multiset>::const_iterator cit_;
+ multiset<recursive_multiset>::reverse_iterator rit_;
+ multiset<recursive_multiset>::const_reverse_iterator crit_;
+
+ friend bool operator< (const recursive_multiset &a, const recursive_multiset &b)
+ { return a.id_ < b.id_; }
+};
+
+template<class C>
+void test_move()
+{
+ //Now test move semantics
+ C original;
+ original.emplace();
+ C move_ctor(boost::move(original));
+ C move_assign;
+ move_assign.emplace();
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+}
+
+bool node_type_test()
+{
+ using namespace boost::container;
+ {
+ typedef set<test::movable_int> set_type;
+ set_type src;
+ {
+ test::movable_int mv_1(1), mv_2(2), mv_3(3);
+ src.emplace(boost::move(mv_1));
+ src.emplace(boost::move(mv_2));
+ src.emplace(boost::move(mv_3));
+ }
+ if(src.size() != 3)
+ return false;
+
+ set_type dst;
+ {
+ test::movable_int mv_3(3);
+ dst.emplace(boost::move(mv_3));
+ }
+
+ if(dst.size() != 1)
+ return false;
+
+ const test::movable_int mv_1(1);
+ const test::movable_int mv_2(2);
+ const test::movable_int mv_3(3);
+ const test::movable_int mv_33(33);
+ set_type::insert_return_type r;
+
+ r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
+ if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
+ return false;
+ r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
+ if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
+ return false;
+ r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
+ if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
+ return false;
+ r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
+
+ if(!src.empty())
+ return false;
+ if(dst.size() != 3)
+ return false;
+ if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.value() == mv_3) )
+ return false;
+ }
+
+ {
+ typedef multiset<test::movable_int> multiset_type;
+ multiset_type src;
+ {
+ test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3);
+ src.emplace(boost::move(mv_1));
+ src.emplace(boost::move(mv_2));
+ src.emplace(boost::move(mv_3));
+ src.emplace_hint(src.begin(), boost::move(mv_3bis));
+ }
+ if(src.size() != 4)
+ return false;
+
+ multiset_type dst;
+ {
+ test::movable_int mv_3(3);
+ dst.emplace(boost::move(mv_3));
+ }
+
+ if(dst.size() != 1)
+ return false;
+
+ const test::movable_int mv_1(1);
+ const test::movable_int mv_2(2);
+ const test::movable_int mv_3(3);
+ const test::movable_int mv_4(4);
+ multiset_type::iterator r;
+
+ multiset_type::node_type nt(src.extract(mv_3));
+ r = dst.insert(dst.begin(), boost::move(nt));
+ if(! (*r == mv_3 && dst.find(mv_3) == r && nt.empty()) )
+ return false;
+
+ nt = src.extract(src.find(mv_1));
+ r = dst.insert(boost::move(nt)); // Iterator version, successful
+ if(! (*r == mv_1 && nt.empty()) )
+ return false;
+
+ nt = src.extract(mv_2);
+ r = dst.insert(boost::move(nt)); // Key type version, successful
+ if(! (*r == mv_2 && nt.empty()) )
+ return false;
+
+ r = dst.insert(src.extract(mv_3)); // Key type version, successful
+ if(! (*r == mv_3 && r == --multiset_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
+ return false;
+
+ r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
+ if(! (r == dst.end()) )
+ return false;
+
+ if(!src.empty())
+ return false;
+ if(dst.size() != 5)
+ return false;
+ }
+ return true;
+}
+
+struct boost_container_set;
+struct boost_container_multiset;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_set>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::set<T, std::less<T>, Allocator> type;
+ };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_multiset>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::multiset<T, std::less<T>, Allocator> type;
+ };
+};
+
+bool constructor_template_auto_deduction_test()
+{
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ using namespace boost::container;
+ const std::size_t NumElements = 100;
+ {
+ std::set<int> int_set;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_set.insert(static_cast<int>(i));
+ }
+ std::multiset<int> int_mset;
+ for (std::size_t i = 0; i != NumElements; ++i) {
+ int_mset.insert(static_cast<int>(i));
+ }
+
+ typedef std::less<int> comp_int_t;
+ typedef std::allocator<int> alloc_int_t;
+
+ //range
+ {
+ auto fset = set(int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = set(int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = set(int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+
+ //ordered_unique_range / ordered_range
+
+ //range
+ {
+ auto fset = set(ordered_unique_range, int_set.begin(), int_set.end());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp
+ {
+ auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+comp+alloc
+ {
+ auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ //range+alloc
+ {
+ auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_set, fset))
+ return false;
+ auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t());
+ if (!CheckEqualContainers(int_mset, fmset))
+ return false;
+ }
+ }
+#endif
+ return true;
+}
+
+}}} //boost::container::test
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+struct GetAllocatorSet
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef set < ValueType
+ , std::less<ValueType>
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ , typename boost::container::tree_assoc_options
+ < boost::container::tree_type<tree_type_value>
+ >::type
+ > set_type;
+
+ typedef multiset < ValueType
+ , std::less<ValueType>
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ , typename boost::container::tree_assoc_options
+ < boost::container::tree_type<tree_type_value>
+ >::type
+ > multiset_type;
+ };
+};
+
+void test_merge_from_different_comparison()
+{
+ set<int> set1;
+ set<int, std::greater<int> > set2;
+ set1.merge(set2);
+}
+
+bool test_heterogeneous_lookups()
+{
+ typedef set<int, test::less_transparent> set_t;
+ typedef multiset<int, test::less_transparent> mset_t;
+
+ set_t set1;
+ mset_t mset1;
+
+ const set_t &cset1 = set1;
+ const mset_t &cmset1 = mset1;
+
+ set1.insert(1);
+ set1.insert(1);
+ set1.insert(2);
+ set1.insert(2);
+ set1.insert(3);
+
+ mset1.insert(1);
+ mset1.insert(1);
+ mset1.insert(2);
+ mset1.insert(2);
+ mset1.insert(3);
+
+ const test::non_copymovable_int find_me(2);
+
+ //find
+ if(*set1.find(find_me) != 2)
+ return false;
+ if(*cset1.find(find_me) != 2)
+ return false;
+ if(*mset1.find(find_me) != 2)
+ return false;
+ if(*cmset1.find(find_me) != 2)
+ return false;
+
+ //count
+ if(set1.count(find_me) != 1)
+ return false;
+ if(cset1.count(find_me) != 1)
+ return false;
+ if(mset1.count(find_me) != 2)
+ return false;
+ if(cmset1.count(find_me) != 2)
+ return false;
+
+ //contains
+ if(!set1.contains(find_me))
+ return false;
+ if(!cset1.contains(find_me))
+ return false;
+ if(!mset1.contains(find_me))
+ return false;
+ if(!cmset1.contains(find_me))
+ return false;
+
+ //lower_bound
+ if(*set1.lower_bound(find_me) != 2)
+ return false;
+ if(*cset1.lower_bound(find_me) != 2)
+ return false;
+ if(*mset1.lower_bound(find_me) != 2)
+ return false;
+ if(*cmset1.lower_bound(find_me) != 2)
+ return false;
+
+ //upper_bound
+ if(*set1.upper_bound(find_me) != 3)
+ return false;
+ if(*cset1.upper_bound(find_me) != 3)
+ return false;
+ if(*mset1.upper_bound(find_me) != 3)
+ return false;
+ if(*cmset1.upper_bound(find_me) != 3)
+ return false;
+
+ //equal_range
+ if(*set1.equal_range(find_me).first != 2)
+ return false;
+ if(*cset1.equal_range(find_me).second != 3)
+ return false;
+ if(*mset1.equal_range(find_me).first != 2)
+ return false;
+ if(*cmset1.equal_range(find_me).second != 3)
+ return false;
+
+ return true;
+}
+
+int main ()
+{
+ //Recursive container instantiation
+ {
+ set<recursive_set> set_;
+ multiset<recursive_multiset> multiset_;
+ }
+ //Allocator argument container
+ {
+ set<int> set_((set<int>::allocator_type()));
+ multiset<int> multiset_((multiset<int>::allocator_type()));
+ }
+ //Now test move semantics
+ {
+ test_move<set<recursive_set> >();
+ test_move<multiset<recursive_multiset> >();
+ }
+ //Test std::pair value type as tree has workarounds to make old std::pair
+ //implementations movable that can break things
+ {
+ boost::container::set<std::pair<int,int> > s;
+ std::pair<int,int> p(0, 0);
+ s.insert(p);
+ s.emplace(p);
+ }
+
+ if (!boost::container::test::instantiate_constructors<set<int>, multiset<int> >())
+ return 1;
+
+ test_merge_from_different_comparison();
+
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction test
+ ////////////////////////////////////
+ if (!test::constructor_template_auto_deduction_test()) {
+ return 1;
+ }
+
+ if(!test_heterogeneous_lookups())
+ return 1;
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ {
+ typedef std::set<int> MyStdSet;
+ typedef std::multiset<int> MyStdMultiSet;
+
+ if (0 != test::set_test
+ < GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<std::allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void>, avl_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<adaptive_pool<void>, scapegoat_tree>" << std::endl;
+ return 1;
+ }
+
+ ///////////
+
+ if (0 != test::set_test
+ < GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void>, splay_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+
+ if (0 != test::set_test
+ < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::set_type
+ , MyStdSet
+ , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multiset_type
+ , MyStdMultiSet>()) {
+ std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl;
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
+ if(!boost::container::test::test_emplace<set<test::EmplaceInt>, SetOptions>())
+ return 1;
+ if(!boost::container::test::test_emplace<multiset<test::EmplaceInt>, SetOptions>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_set>())
+ return 1;
+
+ if(!boost::container::test::test_propagate_allocator<boost_container_multiset>())
+ return 1;
+
+ if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<set<int> >())
+ return 1;
+
+ if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<multiset<int> >())
+ return 1;
+
+ ////////////////////////////////////
+ // Test optimize_size option
+ ////////////////////////////////////
+ //
+ // set
+ //
+ typedef set< int*, std::less<int*>, std::allocator<int*>
+ , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbset_size_optimized_no;
+
+ typedef set< int*, std::less<int*>, std::allocator<int*>
+ , tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlset_size_optimized_yes;
+ //
+ // multiset
+ //
+ typedef multiset< int*, std::less<int*>, std::allocator<int*>
+ , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmset_size_optimized_yes;
+
+ typedef multiset< int*, std::less<int*>, std::allocator<int*>
+ , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmset_size_optimized_no;
+
+ BOOST_STATIC_ASSERT(sizeof(rbmset_size_optimized_yes) < sizeof(rbset_size_optimized_no));
+ BOOST_STATIC_ASSERT(sizeof(avlset_size_optimized_yes) < sizeof(avlmset_size_optimized_no));
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::set<int> cont_int;
+ cont_int a; a.insert(0); a.insert(1); a.insert(2);
+ boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+ {
+ typedef boost::container::multiset<int> cont_int;
+ cont_int a; a.insert(0); a.insert(1); a.insert(2);
+ boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // Node extraction/insertion testing functions
+ ////////////////////////////////////
+ if(!node_type_test())
+ return 1;
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // set, default allocator
+ {
+ typedef boost::container::set<int> cont;
+ typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(set, default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // set, std::allocator
+ {
+ typedef boost::container::set<int, std::less<int>, std::allocator<int> > cont;
+ typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(set, std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // multiset, default allocator
+ {
+ typedef boost::container::multiset<int> cont;
+ typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(multiset, default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // multiset, std::allocator
+ {
+ typedef boost::container::multiset<int, std::less<int>, std::allocator<int> > cont;
+ typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<tree>::value) {
+ std::cerr << "has_trivial_destructor_after_move(multiset, std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/set_test.hpp b/src/boost/libs/container/test/set_test.hpp
new file mode 100644
index 000000000..7bc3a0933
--- /dev/null
+++ b/src/boost/libs/container/test/set_test.hpp
@@ -0,0 +1,942 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_SET_TEST_HEADER
+#define BOOST_CONTAINER_TEST_SET_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME rebalance
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace test {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class C>
+void set_test_rebalanceable(C &, boost::container::dtl::false_type)
+{}
+
+template<class C>
+void set_test_rebalanceable(C &c, boost::container::dtl::true_type)
+{
+ c.rebalance();
+}
+
+template<class MyBoostSet
+ ,class MyStdSet
+ ,class MyBoostMultiSet
+ ,class MyStdMultiSet>
+int set_test_copyable(boost::container::dtl::false_type)
+{ return 0; }
+
+const int MaxElem = 50;
+
+template<class MyBoostSet
+ ,class MyStdSet
+ ,class MyBoostMultiSet
+ ,class MyStdMultiSet>
+int set_test_copyable(boost::container::dtl::true_type)
+{
+ typedef typename MyBoostSet::value_type IntType;
+
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>();
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset = ::boost::movelib::make_unique<MyBoostMultiSet>();
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset = ::boost::movelib::make_unique<MyStdMultiSet>();
+
+ MyBoostSet &boostset = *pboostset;
+ MyStdSet &stdset = *pstdset;
+ MyBoostMultiSet &boostmultiset = *pboostmultiset;
+ MyStdMultiSet &stdmultiset = *pstdmultiset;
+
+ //Just to test move aware catch conversions
+ boostset.insert(boostset.cbegin(), boostset.cend());
+ boostmultiset.insert(boostmultiset.cbegin(), boostmultiset.cend());
+ boostset.insert(boostset.begin(), boostset.end());
+ boostmultiset.insert(boostmultiset.begin(), boostmultiset.end());
+
+ for(int i = 0; i < MaxElem; ++i){
+ IntType move_me(i);
+ boostset.insert(boost::move(move_me));
+ stdset.insert(i);
+ IntType move_me2(i);
+ boostmultiset.insert(boost::move(move_me2));
+ stdmultiset.insert(i);
+ }
+ if(!CheckEqualContainers(boostset, stdset)) return 1;
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+
+ {
+ //Now, test copy constructor
+ MyBoostSet boostsetcopy(boostset);
+ MyStdSet stdsetcopy(stdset);
+
+ if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+ return 1;
+
+ MyBoostMultiSet boostmsetcopy(boostmultiset);
+ MyStdMultiSet stdmsetcopy(stdmultiset);
+
+ if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+ return 1;
+
+ //And now assignment
+ boostsetcopy =boostset;
+ stdsetcopy = stdset;
+
+ if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+ return 1;
+
+ boostmsetcopy = boostmultiset;
+ stdmsetcopy = stdmultiset;
+
+ if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+ return 1;
+ }
+ {
+ //Now, test copy constructor
+ MyBoostSet boostsetcopy(boostset, typename MyBoostSet::allocator_type());
+ MyStdSet stdsetcopy(stdset);
+
+ if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+ return 1;
+
+ MyBoostMultiSet boostmsetcopy(boostmultiset, typename MyBoostSet::allocator_type());
+ MyStdMultiSet stdmsetcopy(stdmultiset);
+
+ if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+ return 1;
+ }
+ return 0;
+}
+
+
+template<class MyBoostSet
+ ,class MyStdSet
+ ,class MyBoostMultiSet
+ ,class MyStdMultiSet>
+int set_test ()
+{
+ typedef typename MyBoostSet::value_type IntType;
+
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>();
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset = ::boost::movelib::make_unique<MyBoostMultiSet>();
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset = ::boost::movelib::make_unique<MyStdMultiSet>();
+
+ MyBoostSet &boostset = *pboostset;
+ MyStdSet &stdset = *pstdset;
+ MyBoostMultiSet &boostmultiset = *pboostmultiset;
+ MyStdMultiSet &stdmultiset = *pstdmultiset;
+
+ //Test construction from a range
+ { //Set(beg, end, compare)
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = i/2;
+ }
+ IntType aux_vect3[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect3[i] = boost::move(move_me);
+ }
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+ (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::key_compare());
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset2 = ::boost::movelib::make_unique<MyStdSet>(&aux_vect2[0], &aux_vect2[0]+50);
+ if(!test::CheckEqualContainers(*pboostset2, *pstdset2)) return 1;
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+ (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::key_compare());
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset2 = ::boost::movelib::make_unique<MyStdMultiSet>(&aux_vect2[0], &aux_vect2[0]+50);
+ if(!test::CheckEqualContainers(*pboostmultiset2, *pstdmultiset2)) return 1;
+ }
+ { //Set(beg, end, alloc)
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = i/2;
+ }
+ IntType aux_vect3[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect3[i] = boost::move(move_me);
+ }
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+ (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset2 = ::boost::movelib::make_unique<MyStdSet>(&aux_vect2[0], &aux_vect2[0]+50);
+ if(!test::CheckEqualContainers(*pboostset2, *pstdset2)) return 1;
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+ (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset2 = ::boost::movelib::make_unique<MyStdMultiSet>(&aux_vect2[0], &aux_vect2[0]+50);
+ if(!test::CheckEqualContainers(*pboostmultiset2, *pstdmultiset2)) return 1;
+ }
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = i/2;
+ }
+ IntType aux_vect3[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i/2);
+ aux_vect3[i] = boost::move(move_me);
+ }
+
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+ ( boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(aux_vect + 50));
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset2 = ::boost::movelib::make_unique<MyStdSet>
+ (&aux_vect2[0], &aux_vect2[0] + 50);
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+ ( boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(aux_vect3 + 50));
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset2 = ::boost::movelib::make_unique<MyStdMultiSet>
+ (&aux_vect2[0], &aux_vect2[0] + 50);
+
+ MyBoostSet &boostset2 = *pboostset2;
+ MyStdSet &stdset2 = *pstdset2;
+ MyBoostMultiSet &boostmultiset2 = *pboostmultiset2;
+ MyStdMultiSet &stdmultiset2 = *pstdmultiset2;
+
+ if(!CheckEqualContainers(boostset2, stdset2)){
+ std::cout << "Error in construct<MyBoostSet>(MyBoostSet2)" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset2, stdmultiset2)){
+ std::cout << "Error in construct<MyBoostMultiSet>(MyBoostMultiSet2)" << std::endl;
+ return 1;
+ }
+
+ //ordered range insertion
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i);
+ aux_vect[i] = boost::move(move_me);
+ }
+
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = i;
+ }
+
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(i);
+ aux_vect3[i] = boost::move(move_me);
+ }
+
+ //some comparison operators
+ if(!(boostset2 == boostset2))
+ return 1;
+ if(boostset2 != boostset2)
+ return 1;
+ if(boostset2 < boostset2)
+ return 1;
+ if(boostset2 > boostset2)
+ return 1;
+ if(!(boostset2 <= boostset2))
+ return 1;
+ if(!(boostset2 >= boostset2))
+ return 1;
+
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset3 = ::boost::movelib::make_unique<MyBoostSet>
+ ( ordered_unique_range
+ , boost::make_move_iterator(&aux_vect[0])
+ , boost::make_move_iterator(&aux_vect[0] + 50));
+ ::boost::movelib::unique_ptr<MyStdSet> const pstdset3 = ::boost::movelib::make_unique<MyStdSet>
+ (&aux_vect2[0], &aux_vect2[0] + 50);
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset3 = ::boost::movelib::make_unique<MyBoostMultiSet>
+ ( ordered_range
+ , boost::make_move_iterator(&aux_vect3[0])
+ , boost::make_move_iterator(aux_vect3 + 50));
+ ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset3 = ::boost::movelib::make_unique<MyStdMultiSet>
+ (&aux_vect2[0], &aux_vect2[0] + 50);
+
+ MyBoostSet &boostset3 = *pboostset3;
+ MyStdSet &stdset3 = *pstdset3;
+ MyBoostMultiSet &boostmultiset3 = *pboostmultiset3;
+ MyStdMultiSet &stdmultiset3 = *pstdmultiset3;
+
+ if(!CheckEqualContainers(boostset3, stdset3)){
+ std::cout << "Error in construct<MyBoostSet>(MyBoostSet3)" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset3, stdmultiset3)){
+ std::cout << "Error in construct<MyBoostMultiSet>(MyBoostMultiSet3)" << std::endl;
+ return 1;
+ }
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ IntType move_me(i);
+ boostset.insert(boost::move(move_me));
+ stdset.insert(i);
+ boostset.insert(IntType(i));
+ stdset.insert(i);
+ IntType move_me2(i);
+ boostmultiset.insert(boost::move(move_me2));
+ stdmultiset.insert(i);
+ boostmultiset.insert(IntType(i));
+ stdmultiset.insert(i);
+ }
+
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boost::move(move_me)" << std::endl;
+ return 1;
+ }
+
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boost::move(move_me)" << std::endl;
+ return 1;
+ }
+
+ typename MyBoostSet::iterator it = boostset.begin();
+ typename MyBoostSet::const_iterator cit = it;
+ (void)cit;
+
+ boostset.erase(boostset.begin());
+ stdset.erase(stdset.begin());
+ boostmultiset.erase(boostmultiset.begin());
+ stdmultiset.erase(stdmultiset.begin());
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.erase(boostset.begin())" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.erase(boostmultiset.begin())" << std::endl;
+ return 1;
+ }
+
+ boostset.erase(boostset.begin());
+ stdset.erase(stdset.begin());
+ boostmultiset.erase(boostmultiset.begin());
+ stdmultiset.erase(stdmultiset.begin());
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.erase(boostset.begin())" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.erase(boostmultiset.begin())" << std::endl;
+ return 1;
+ }
+
+ //Swapping test
+ MyBoostSet tmpboosteset2;
+ MyStdSet tmpstdset2;
+ MyBoostMultiSet tmpboostemultiset2;
+ MyStdMultiSet tmpstdmultiset2;
+ boostset.swap(tmpboosteset2);
+ stdset.swap(tmpstdset2);
+ boostmultiset.swap(tmpboostemultiset2);
+ stdmultiset.swap(tmpstdmultiset2);
+ boostset.swap(tmpboosteset2);
+ stdset.swap(tmpstdset2);
+ boostmultiset.swap(tmpboostemultiset2);
+ stdmultiset.swap(tmpstdmultiset2);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.swap(tmpboostemultiset2)" << std::endl;
+ return 1;
+ }
+
+ //Insertion from other container
+ //Initialize values
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ IntType aux_vect3[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect3[i] = boost::move(move_me);
+ }
+
+ boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
+ stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
+ return 1;
+ }
+ boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50));
+ stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl;
+ return 1;
+ }
+
+ for(int i = 0, j = static_cast<int>(boostset.size()); i < j; ++i){
+ IntType erase_me(i);
+ boostset.erase(erase_me);
+ stdset.erase(i);
+ boostmultiset.erase(erase_me);
+ stdmultiset.erase(i);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.erase(erase_me)" << boostset.size() << " " << stdset.size() << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.erase(erase_me)" << std::endl;
+ return 1;
+ }
+ }
+ }
+ {
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect[i] = boost::move(move_me);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ IntType aux_vect3[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect3[i] = boost::move(move_me);
+ }
+
+ IntType aux_vect4[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect4[i] = boost::move(move_me);
+ }
+
+ IntType aux_vect5[50];
+ for(int i = 0; i < 50; ++i){
+ IntType move_me(-1);
+ aux_vect5[i] = boost::move(move_me);
+ }
+
+ boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
+ boostset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50));
+ stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
+ return 1;
+ }
+ boostmultiset.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(&aux_vect4[0] + 50));
+ boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(&aux_vect5[0] + 50));
+ stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl;
+ return 1;
+ }
+
+ boostset.erase(*boostset.begin());
+ stdset.erase(*stdset.begin());
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.erase(*boostset.begin())" << std::endl;
+ return 1;
+ }
+ boostmultiset.erase(*boostmultiset.begin());
+ stdmultiset.erase(*stdmultiset.begin());
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.erase(*boostmultiset.begin())" << std::endl;
+ return 1;
+ }
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ IntType move_me(i);
+ boostset.insert(boost::move(move_me));
+ stdset.insert(i);
+ IntType move_me2(i);
+ boostmultiset.insert(boost::move(move_me2));
+ stdmultiset.insert(i);
+ }
+
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boost::move(move_me)) try 2" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boost::move(move_me2)) try 2" << std::endl;
+ return 1;
+ }
+
+ for(int i = 0; i < MaxElem; ++i){
+ {
+ IntType move_me(i);
+ boostset.insert(boostset.begin(), boost::move(move_me));
+ stdset.insert(stdset.begin(), i);
+ //PrintContainers(boostset, stdset);
+ IntType move_me2(i);
+ boostmultiset.insert(boostmultiset.begin(), boost::move(move_me2));
+ stdmultiset.insert(stdmultiset.begin(), i);
+ //PrintContainers(boostmultiset, stdmultiset);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boostset.begin(), boost::move(move_me))" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boostmultiset.begin(), boost::move(move_me2))" << std::endl;
+ return 1;
+ }
+
+ IntType move_me3(i);
+ boostset.insert(boostset.end(), boost::move(move_me3));
+ stdset.insert(stdset.end(), i);
+ IntType move_me4(i);
+ boostmultiset.insert(boostmultiset.end(), boost::move(move_me4));
+ stdmultiset.insert(stdmultiset.end(), i);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boostset.end(), boost::move(move_me3))" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boostmultiset.end(), boost::move(move_me4))" << std::endl;
+ return 1;
+ }
+ }
+ {
+ IntType move_me(i);
+ boostset.insert(boostset.upper_bound(move_me), boost::move(move_me));
+ stdset.insert(stdset.upper_bound(i), i);
+ //PrintContainers(boostset, stdset);
+ IntType move_me2(i);
+ boostmultiset.insert(boostmultiset.upper_bound(move_me2), boost::move(move_me2));
+ stdmultiset.insert(stdmultiset.upper_bound(i), i);
+ //PrintContainers(boostmultiset, stdmultiset);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boostset.upper_bound(move_me), boost::move(move_me))" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boostmultiset.upper_bound(move_me2), boost::move(move_me2))" << std::endl;
+ return 1;
+ }
+
+ }
+ {
+ IntType move_me(i);
+ IntType move_me2(i);
+ boostset.insert(boostset.lower_bound(move_me), boost::move(move_me2));
+ stdset.insert(stdset.lower_bound(i), i);
+ //PrintContainers(boostset, stdset);
+ move_me2 = i;
+ boostmultiset.insert(boostmultiset.lower_bound(move_me2), boost::move(move_me2));
+ stdmultiset.insert(stdmultiset.lower_bound(i), i);
+ //PrintContainers(boostmultiset, stdmultiset);
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.insert(boostset.lower_bound(move_me), boost::move(move_me2))" << std::endl;
+ return 1;
+ }
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.insert(boostmultiset.lower_bound(move_me2), boost::move(move_me2))" << std::endl;
+ return 1;
+ }
+ set_test_rebalanceable(boostset
+ , dtl::bool_<has_member_function_callable_with_rebalance<MyBoostSet>::value>());
+ if(!CheckEqualContainers(boostset, stdset)){
+ std::cout << "Error in boostset.rebalance()" << std::endl;
+ return 1;
+ }
+ set_test_rebalanceable(boostmultiset
+ , dtl::bool_<has_member_function_callable_with_rebalance<MyBoostMultiSet>::value>());
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+ std::cout << "Error in boostmultiset.rebalance()" << std::endl;
+ return 1;
+ }
+ }
+ }
+
+ //Compare count with std containers
+ for(int i = 0; i < MaxElem; ++i){
+ IntType k(i);
+ if(boostset.count(k) != stdset.count(i)){
+ return -1;
+ }
+
+ if(boostset.contains(k) != (stdset.find(i) != stdset.end())){
+ return -1;
+ }
+
+ if(boostmultiset.count(k) != stdmultiset.count(i)){
+ return -1;
+ }
+
+ if(boostmultiset.contains(k) != (stdmultiset.find(i) != stdmultiset.end())){
+ return -1;
+ }
+ }
+
+ //Compare find/lower_bound/upper_bound in set
+ {
+ typename MyBoostSet::iterator bs_b = boostset.begin();
+ typename MyBoostSet::iterator bs_e = boostset.end();
+ typename MyStdSet::iterator ss_b = stdset.begin();
+
+ std::size_t i = 0;
+ while(bs_b != bs_e){
+ ++i;
+ typename MyBoostSet::iterator bs_i;
+ typename MyStdSet::iterator ss_i;
+ //find
+ bs_i = boostset.find(*bs_b);
+ ss_i = stdset.find(*ss_b);
+ if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+ return -1;
+ }
+ //lower bound
+ bs_i = boostset.lower_bound(*bs_b);
+ ss_i = stdset.lower_bound(*ss_b);
+ if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+ return -1;
+ }
+ //upper bound
+ bs_i = boostset.upper_bound(*bs_b);
+ ss_i = stdset.upper_bound(*ss_b);
+ if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+ return -1;
+ }
+ //equal range
+ std::pair<typename MyBoostSet::iterator
+ ,typename MyBoostSet::iterator> bs_ip;
+ std::pair<typename MyStdSet::iterator
+ ,typename MyStdSet::iterator> ss_ip;
+ bs_ip = boostset.equal_range(*bs_b);
+ ss_ip = stdset.equal_range(*ss_b);
+ if(!CheckEqualIt(bs_ip.first, ss_ip.first, boostset, stdset)){
+ return -1;
+ }
+ if(!CheckEqualIt(bs_ip.second, ss_ip.second, boostset, stdset)){
+ return -1;
+ }
+ ++bs_b;
+ ++ss_b;
+ }
+ }
+ //Compare find/lower_bound/upper_bound in multiset
+ {
+ typename MyBoostMultiSet::iterator bm_b = boostmultiset.begin();
+ typename MyBoostMultiSet::iterator bm_e = boostmultiset.end();
+ typename MyStdMultiSet::iterator sm_b = stdmultiset.begin();
+
+ while(bm_b != bm_e){
+ typename MyBoostMultiSet::iterator bm_i;
+ typename MyStdMultiSet::iterator sm_i;
+ //find
+ bm_i = boostmultiset.find(*bm_b);
+ sm_i = stdmultiset.find(*sm_b);
+ if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+ return -1;
+ }
+ //lower bound
+ bm_i = boostmultiset.lower_bound(*bm_b);
+ sm_i = stdmultiset.lower_bound(*sm_b);
+ if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+ return -1;
+ }
+ //upper bound
+ bm_i = boostmultiset.upper_bound(*bm_b);
+ sm_i = stdmultiset.upper_bound(*sm_b);
+ if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+ return -1;
+ }
+ //equal range
+ std::pair<typename MyBoostMultiSet::iterator
+ ,typename MyBoostMultiSet::iterator> bm_ip;
+ std::pair<typename MyStdMultiSet::iterator
+ ,typename MyStdMultiSet::iterator> sm_ip;
+ bm_ip = boostmultiset.equal_range(*bm_b);
+ sm_ip = stdmultiset.equal_range(*sm_b);
+ if(!CheckEqualIt(bm_ip.first, sm_ip.first, boostmultiset, stdmultiset)){
+ return -1;
+ }
+ if(!CheckEqualIt(bm_ip.second, sm_ip.second, boostmultiset, stdmultiset)){
+ return -1;
+ }
+ ++bm_b;
+ ++sm_b;
+ }
+ }
+
+ //Now do count exercise
+ boostset.erase(boostset.begin(), boostset.end());
+ boostmultiset.erase(boostmultiset.begin(), boostmultiset.end());
+ boostset.clear();
+ boostmultiset.clear();
+
+ for(int j = 0; j < 3; ++j)
+ for(int i = 0; i < 100; ++i){
+ IntType move_me(i);
+ boostset.insert(boost::move(move_me));
+ IntType move_me2(i);
+ boostmultiset.insert(boost::move(move_me2));
+ IntType count_me(i);
+ if(boostset.count(count_me) != typename MyBoostMultiSet::size_type(1)){
+ std::cout << "Error in boostset.count(count_me)" << std::endl;
+ return 1;
+ }
+ if(boostmultiset.count(count_me) != typename MyBoostMultiSet::size_type(j+1)){
+ std::cout << "Error in boostmultiset.count(count_me)" << std::endl;
+ return 1;
+ }
+ }
+
+ { //merge
+ ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>();
+ ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>();
+
+ MyBoostSet &boostset2 = *pboostset2;
+ MyBoostMultiSet &boostmultiset2 = *pboostmultiset2;
+
+ boostset.clear();
+ boostset2.clear();
+ boostmultiset.clear();
+ boostmultiset2.clear();
+ stdset.clear();
+ stdmultiset.clear();
+
+ {
+ IntType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect[i] = i;
+ }
+
+ IntType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect2[i] = MaxElem/2+i;
+ }
+ IntType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect3[i] = MaxElem*2/2+i;
+ }
+ boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+ boostmultiset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdset.insert(i);
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdset.insert(MaxElem/2+i);
+ }
+
+ boostset.merge(boost::move(boostset2));
+ if(!CheckEqualContainers(boostset, stdset)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ stdset.insert(MaxElem*2/2+i);
+ }
+
+ boostset.merge(boost::move(boostmultiset2));
+ if(!CheckEqualContainers(boostset, stdset)) return 1;
+
+ boostset.clear();
+ boostset2.clear();
+ boostmultiset.clear();
+ boostmultiset2.clear();
+ stdset.clear();
+ stdmultiset.clear();
+ {
+ IntType aux_vect[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect[i] = i;
+ }
+
+ IntType aux_vect2[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect2[i] = MaxElem/2+i;
+ }
+ IntType aux_vect3[MaxElem];
+ for(int i = 0; i < MaxElem; ++i){
+ aux_vect3[i] = MaxElem*2/2+i;
+ }
+ boostmultiset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+ boostmultiset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+ boostset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultiset.insert(i);
+ }
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultiset.insert(MaxElem/2+i);
+ }
+ boostmultiset.merge(boost::move(boostmultiset2));
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+
+ for(int i = 0; i < MaxElem; ++i){
+ stdmultiset.insert(MaxElem*2/2+i);
+ }
+
+ boostmultiset.merge(boost::move(boostset2));
+ if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+ }
+
+ if(set_test_copyable<MyBoostSet, MyStdSet, MyBoostMultiSet, MyStdMultiSet>
+ (dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+ return 1;
+ }
+
+ return 0;
+}
+
+template<typename SetType>
+bool test_set_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ std::initializer_list<int> il = { 1, 2, 3, 4, 5, 5 };
+ std::initializer_list<int> ilu = { 1, 2, 3, 4, 5 };
+ SetType expected(il.begin(), il.end());
+ SetType expectedu(ilu.begin(), ilu.end());
+ {
+ SetType sil((il));
+ if (sil != expected)
+ return false;
+
+ SetType sila(il, typename SetType::allocator_type());
+ if (sila != expected)
+ return false;
+
+ SetType silca(il, typename SetType::key_compare(), typename SetType::allocator_type());
+ if (silca != expected)
+ return false;
+
+ SetType sil_ordered(ordered_unique_range, ilu);
+ if (sil_ordered != expectedu)
+ return false;
+
+ SetType sil_assign = { 99, 100, 101, 102, 103, 104, 105 };
+ sil_assign = il;
+ if (sil_assign != expected)
+ return false;
+ }
+ {
+ SetType sil;
+ sil.insert(il);
+ if (sil != expected)
+ return false;
+ }
+ return true;
+#endif
+ return true;
+}
+
+template<typename SetType, typename MultisetType>
+bool instantiate_constructors()
+{
+ {
+ typedef typename SetType::value_type value_type;
+ typename SetType::key_compare comp;
+ typename SetType::allocator_type a;
+ value_type value;
+ {
+ SetType s0;
+ SetType s1(comp);
+ SetType s2(a);
+ SetType s3(comp, a);
+ }
+ {
+ SetType s0(&value, &value);
+ SetType s1(&value, &value ,comp);
+ SetType s2(&value, &value ,a);
+ SetType s3(&value, &value ,comp, a);
+ }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ {
+ SetType s0({ 0 });
+ SetType s1({ 0 },comp);
+ SetType s2({ 0 },a);
+ SetType s3({ 0 },comp, a);
+ }
+ {
+ std::initializer_list<value_type> il{0};
+ SetType s0(ordered_unique_range, il);
+ SetType s1(ordered_unique_range, il,comp);
+ SetType s3(ordered_unique_range, il,comp, a);
+ }
+ #endif
+ {
+ SetType s0(ordered_unique_range, &value, &value);
+ SetType s1(ordered_unique_range, &value, &value ,comp);
+ SetType s2(ordered_unique_range, &value, &value ,comp, a);
+ }
+ }
+
+ {
+ typedef typename MultisetType::value_type value_type;
+ typename MultisetType::key_compare comp;
+ typename MultisetType::allocator_type a;
+ value_type value;
+ {
+ MultisetType s0;
+ MultisetType s1(comp);
+ MultisetType s2(a);
+ MultisetType s3(comp, a);
+ }
+ {
+ MultisetType s0(&value, &value);
+ MultisetType s1(&value, &value ,comp);
+ MultisetType s2(&value, &value ,a);
+ MultisetType s3(&value, &value ,comp, a);
+ }
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ {
+ MultisetType s0({ 0 });
+ MultisetType s1({ 0 },comp);
+ MultisetType s2({ 0 },a);
+ MultisetType s3({ 0 },comp, a);
+ }
+ {
+ std::initializer_list<value_type>il{0};
+ MultisetType s0(ordered_range, il);
+ MultisetType s1(ordered_range, il,comp);
+ MultisetType s3(ordered_range, il,comp, a);
+ }
+ #endif
+ {
+ MultisetType s0(ordered_range, &value, &value);
+ MultisetType s1(ordered_range, &value, &value ,comp);
+ MultisetType s2(ordered_range, &value, &value ,comp, a);
+ }
+ }
+ return true;
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/src/boost/libs/container/test/slist_test.cpp b/src/boost/libs/container/test/slist_test.cpp
new file mode 100644
index 000000000..08943448a
--- /dev/null
+++ b/src/boost/libs/container/test/slist_test.cpp
@@ -0,0 +1,290 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/node_allocator.hpp>
+
+#include <memory>
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+class recursive_slist
+{
+public:
+ int id_;
+ slist<recursive_slist> slist_;
+ slist<recursive_slist>::iterator it_;
+ slist<recursive_slist>::const_iterator cit_;
+
+ recursive_slist &operator=(const recursive_slist &o)
+ { slist_ = o.slist_; return *this; }
+};
+
+void recursive_slist_test()//Test for recursive types
+{
+ slist<recursive_slist> recursive_list_list;
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef slist< ValueType
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ > type;
+ };
+};
+
+bool test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ const std::initializer_list<int> il = {5, 10, 15};
+ const slist<int> expected_list(il.begin(), il.end());
+ {
+ slist<int> sl = il;
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ slist<int> sl = {1, 2};
+ sl = il;
+ if(sl != expected_list)
+ return false;
+ }
+ {
+ slist<int> sl({ 1, 2 }, slist<int>::allocator_type());
+ sl = il;
+ if (sl != expected_list)
+ return false;
+ }
+ {
+ slist<int> sl = {4, 5};
+ sl.assign(il);
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ slist<int> sl = {15};
+ sl.insert(sl.cbegin(), {5, 10});
+ if(sl != expected_list)
+ return false;
+ }
+
+ {
+ slist<int> sl = {5};
+ sl.insert_after(sl.cbegin(), {10, 15});
+ if(sl != expected_list)
+ return false;
+ }
+ return true;
+#endif
+ return true;
+}
+
+bool test_for_splice()
+{
+ {
+ slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
+ slist<int> list2;
+ slist<int> expected1; expected1.push_front(3); expected1.push_front(2); expected1.push_front(0);
+ slist<int> expected2; expected2.push_front(1);
+
+ list2.splice(list2.begin(), list1, ++list1.begin());
+
+ if (!(expected1 == list1 && expected2 == list2))
+ return false;
+ }
+ {
+ slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
+ slist<int> list2;
+ slist<int> expected1;
+ slist<int> expected2; expected2.push_front(3); expected2.push_front(2); expected2.push_front(1); expected2.push_front(0);
+
+ list2.splice(list2.begin(), list1, list1.begin(), list1.end());
+
+ if (!(expected1 == list1 && expected2 == list2))
+ return false;
+ }
+ return true;
+}
+
+struct boost_container_slist;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_slist>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::slist<T, Allocator> type;
+ };
+};
+
+}}}
+
+int main ()
+{
+ recursive_slist_test();
+ {
+ //Now test move semantics
+ slist<recursive_slist> original;
+ slist<recursive_slist> move_ctor(boost::move(original));
+ slist<recursive_slist> move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+ {
+ slist<recursive_slist> recursive, copy;
+ //Test to test both move emulations
+ if(!copy.size()){
+ copy = recursive;
+ }
+ }
+ }
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ if (test::list_test<slist<int, std::allocator<int> >, false>())
+ return 1;
+ if (test::list_test<slist<int>, false>())
+ return 1;
+ if (test::list_test<slist<int, node_allocator<int> >, false>())
+ return 1;
+ if (test::list_test<slist<test::movable_int>, false>())
+ return 1;
+ if (test::list_test<slist<test::movable_and_copyable_int>, false>())
+ return 1;
+ if (test::list_test<slist<test::copyable_int>, false>())
+ return 1;
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)
+ (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE | test::EMPLACE_AFTER);
+
+ if(!boost::container::test::test_emplace
+ < slist<test::EmplaceInt>, Options>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_slist>())
+ return 1;
+
+ ////////////////////////////////////
+ // Initializer lists
+ ////////////////////////////////////
+ if(!test_support_for_initializer_list())
+ return 1;
+
+ ////////////////////////////////////
+ // Splice testing
+ ////////////////////////////////////
+ if(!test_for_splice())
+ return 1;
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::slist<int> vector_int;
+ vector_int a; a.push_front(2); a.push_front(1); a.push_front(0);
+ boost::intrusive::test::test_iterator_forward< boost::container::slist<int> >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction Tests
+ ////////////////////////////////////
+ {
+ auto gold = std::list{ 1, 2, 3 };
+ auto test = boost::container::slist(gold.begin(), gold.end());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (test.front() != 1)
+ return 1;
+ test.pop_front();
+ if (test.front() != 2)
+ return 1;
+ test.pop_front();
+ if (test.front() != 3)
+ return 1;
+ test.pop_front();
+ }
+ {
+ auto gold = std::list{ 1, 2, 3 };
+ auto test = boost::container::slist(gold.begin(), gold.end(), new_allocator<int>());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (test.front() != 1)
+ return 1;
+ test.pop_front();
+ if (test.front() != 2)
+ return 1;
+ test.pop_front();
+ if (test.front() != 3)
+ return 1;
+ test.pop_front();
+ }
+#endif
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::slist<int> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::slist<int, std::allocator<int> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
+
diff --git a/src/boost/libs/container/test/small_vector_options_test.cpp b/src/boost/libs/container/test/small_vector_options_test.cpp
new file mode 100644
index 000000000..73e485536
--- /dev/null
+++ b/src/boost/libs/container/test/small_vector_options_test.cpp
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/small_vector.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/assert.hpp>
+using namespace boost::container;
+
+const std::size_t Capacity = 10u;
+
+void test_alignment()
+{
+ { //extended alignment
+ const std::size_t extended_alignment = sizeof(int)*4u;
+ BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of<int>::value);
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = small_vector_options_t< inplace_alignment<extended_alignment> >;
+ #else
+ typedef small_vector_options
+ < inplace_alignment<extended_alignment> >::type options_t;
+ #endif
+
+ small_vector<int, Capacity, void, options_t> v;
+ v.resize(v.capacity());
+ BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % extended_alignment) == 0);
+ }
+ { //default alignment
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = small_vector_options_t< inplace_alignment<0> >;
+ #else
+ typedef small_vector_options< inplace_alignment<0> >::type options_t;
+ #endif
+
+ small_vector<int, Capacity, void, options_t> v;
+ v.resize(v.capacity());
+ BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % dtl::alignment_of<int>::value) == 0);
+ }
+}
+
+void test_growth_factor_50()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = small_vector_options_t< growth_factor<growth_factor_50> >;
+ #else
+ typedef small_vector_options
+ < growth_factor<growth_factor_50> >::type options_t;
+ #endif
+
+ small_vector<int, Capacity, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == old_capacity + old_capacity/2);
+}
+
+void test_growth_factor_60()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = small_vector_options_t< growth_factor<growth_factor_60> >;
+ #else
+ typedef small_vector_options
+ < growth_factor<growth_factor_60> >::type options_t;
+ #endif
+
+ small_vector<int, Capacity, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == old_capacity + 3*old_capacity/5);
+}
+
+void test_growth_factor_100()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = small_vector_options_t< growth_factor<growth_factor_100> >;
+ #else
+ typedef small_vector_options
+ < growth_factor<growth_factor_100> >::type options_t;
+ #endif
+
+ small_vector<int, Capacity, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == 2*old_capacity);
+}
+
+int main()
+{
+ test_alignment();
+ test_growth_factor_50();
+ test_growth_factor_60();
+ test_growth_factor_100();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/small_vector_test.cpp b/src/boost/libs/container/test/small_vector_test.cpp
new file mode 100644
index 000000000..315d64ddc
--- /dev/null
+++ b/src/boost/libs/container/test/small_vector_test.cpp
@@ -0,0 +1,236 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/small_vector.hpp>
+#include "vector_test.hpp"
+#include "movable_int.hpp"
+#include "propagate_allocator_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <boost/container/allocator.hpp>
+
+#include <iostream>
+
+struct boost_container_small_vector;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_small_vector>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::small_vector<T, 10, Allocator> type;
+ };
+};
+
+}}} //namespace boost::container::test
+
+bool test_small_vector_base_test()
+{
+ typedef boost::container::small_vector_base<int> smb_t;
+ {
+ typedef boost::container::small_vector<int, 5> sm5_t;
+ BOOST_STATIC_ASSERT(sm5_t::static_capacity == 5);
+ sm5_t sm5;
+ smb_t &smb = sm5;
+ smb.push_back(1);
+ sm5_t sm5_copy(sm5);
+ sm5_copy.push_back(1);
+ if (!boost::container::test::CheckEqualContainers(sm5, smb))
+ return false;
+ }
+ {
+ typedef boost::container::small_vector<int, 7> sm7_t;
+ BOOST_STATIC_ASSERT(sm7_t::static_capacity == 7);
+ sm7_t sm7;
+ smb_t &smb = sm7;
+ smb.push_back(2);
+ sm7_t sm7_copy(sm7);
+ sm7_copy.push_back(2);
+ if (!boost::container::test::CheckEqualContainers(sm7, smb))
+ return false;
+ }
+ {
+ typedef boost::container::small_vector<int, 5> sm5_t;
+ sm5_t sm5;
+ smb_t &smb = sm5;
+ smb.push_back(1);
+ sm5_t sm5_copy(smb);
+ if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy))
+ return false;
+ smb.push_back(2);
+ if(smb.size() != 2){
+ return false;
+ }
+ sm5_copy = smb;
+ if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy))
+ return false;
+ sm5_t sm5_move(boost::move(smb));
+ smb.clear();
+ if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy))
+ return false;
+ smb = sm5_copy;
+ sm5_move = boost::move(smb);
+ smb.clear();
+ if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy))
+ return false;
+ }
+
+ return true;
+}
+
+//small vector has internal storage so some special swap cases must be tested
+bool test_swap()
+{
+ typedef boost::container::small_vector<int, 10> vec;
+ { //v bigger than static capacity, w empty
+ vec v;
+ for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){
+ v.push_back(int(i));
+ }
+ vec w;
+ const std::size_t v_size = v.size();
+ const std::size_t w_size = w.size();
+ v.swap(w);
+ if(v.size() != w_size || w.size() != v_size)
+ return false;
+ }
+ { //v smaller than static capacity, w empty
+ vec v;
+ for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){
+ v.push_back(int(i));
+ }
+ vec w;
+ const std::size_t v_size = v.size();
+ const std::size_t w_size = w.size();
+ v.swap(w);
+ if(v.size() != w_size || w.size() != v_size)
+ return false;
+ }
+ { //v & w smaller than static capacity
+ vec v;
+ for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){
+ v.push_back(int(i));
+ }
+ vec w;
+ for(std::size_t i = 0, max = v.capacity()/2; i != max; ++i){
+ w.push_back(int(i));
+ }
+ const std::size_t v_size = v.size();
+ const std::size_t w_size = w.size();
+ v.swap(w);
+ if(v.size() != w_size || w.size() != v_size)
+ return false;
+ }
+ { //v & w bigger than static capacity
+ vec v;
+ for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){
+ v.push_back(int(i));
+ }
+ vec w;
+ for(std::size_t i = 0, max = v.capacity()*2; i != max; ++i){
+ w.push_back(int(i));
+ }
+ const std::size_t v_size = v.size();
+ const std::size_t w_size = w.size();
+ v.swap(w);
+ if(v.size() != w_size || w.size() != v_size)
+ return false;
+ }
+ return true;
+}
+
+int main()
+{
+ using namespace boost::container;
+
+ if(!test_swap())
+ return 1;
+
+ if(test::vector_test< small_vector<int, 0> >())
+ return 1;
+
+ if(test::vector_test< small_vector<int, 2000> >())
+ return 1;
+
+ ////////////////////////////////////
+ // Default init test
+ ////////////////////////////////////
+ if(!test::default_init_test< small_vector<int, 5, test::default_init_allocator<int> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+ if(!boost::container::test::test_emplace< small_vector<test::EmplaceInt, 5>, Options>()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_small_vector>()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Initializer lists testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+ < boost::container::small_vector<int, 5> >()) {
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Small vector base
+ ////////////////////////////////////
+ if (!test_small_vector_base_test()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::small_vector<int, 0> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::small_vector<int, 0> cont;
+ if (boost::has_trivial_destructor_after_move<cont>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::small_vector<int, 0, std::allocator<int> > cont;
+ if (boost::has_trivial_destructor_after_move<cont>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/stable_vector_test.cpp b/src/boost/libs/container/test/stable_vector_test.cpp
new file mode 100644
index 000000000..e0fb5867f
--- /dev/null
+++ b/src/boost/libs/container/test/stable_vector_test.cpp
@@ -0,0 +1,227 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/node_allocator.hpp>
+
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+class recursive_vector
+{
+ public:
+ int id_;
+ stable_vector<recursive_vector> vector_;
+ stable_vector<recursive_vector>::iterator it_;
+ stable_vector<recursive_vector>::const_iterator cit_;
+ stable_vector<recursive_vector>::reverse_iterator rit_;
+ stable_vector<recursive_vector>::const_reverse_iterator crit_;
+
+ recursive_vector &operator=(const recursive_vector &o)
+ { vector_ = o.vector_; return *this; }
+};
+
+void recursive_vector_test()//Test for recursive types
+{
+ stable_vector<recursive_vector> recursive, copy;
+ //Test to test both move emulations
+ if(!copy.size()){
+ copy = recursive;
+ }
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef stable_vector< ValueType
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ > type;
+ };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+ if(test::vector_test<MyCont>())
+ return 1;
+ if(test::vector_test<MyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyCont>())
+ return 1;
+
+ return 0;
+}
+
+struct boost_container_stable_vector;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_stable_vector>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::stable_vector<T, Allocator> type;
+ };
+};
+
+}}} //namespace boost::container::test
+
+
+int main()
+{
+ recursive_vector_test();
+ {
+ //Now test move semantics
+ stable_vector<recursive_vector> original;
+ stable_vector<recursive_vector> move_ctor(boost::move(original));
+ stable_vector<recursive_vector> move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+ }
+
+ //Test non-copy-move operations
+ {
+ stable_vector<test::non_copymovable_int> sv;
+ sv.emplace_back();
+ sv.resize(10);
+ sv.resize(1);
+ }
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ // std:allocator
+ if(test_cont_variants< std::allocator<void> >()){
+ std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+ return 1;
+ }
+ // boost::container::node_allocator
+ if(test_cont_variants< node_allocator<void> >()){
+ std::cerr << "test_cont_variants< node_allocator<void> > failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Default init test
+ ////////////////////////////////////
+ if(!test::default_init_test< stable_vector<int, test::default_init_allocator<int> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+ if(!boost::container::test::test_emplace
+ < stable_vector<test::EmplaceInt>, Options>())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_stable_vector>())
+ return 1;
+
+ ////////////////////////////////////
+ // Initializer lists testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+ < boost::container::stable_vector<int> >())
+ {
+ std::cerr << "test_methods_with_initializer_list_as_argument failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::stable_vector<int> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction testing
+ ////////////////////////////////////
+ {
+ auto gold = std::vector{ 1, 2, 3 };
+ auto test = boost::container::stable_vector(gold.begin(), gold.end());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+ return 1;
+ }
+ }
+#endif
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::stable_vector<int> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::stable_vector<int, std::allocator<int> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/static_vector_options_test.cpp b/src/boost/libs/container/test/static_vector_options_test.cpp
new file mode 100644
index 000000000..e8965d54f
--- /dev/null
+++ b/src/boost/libs/container/test/static_vector_options_test.cpp
@@ -0,0 +1,124 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_ENABLE_ASSERT_HANDLER
+#include <boost/container/static_vector.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <new> //for bad_alloc
+#include <boost/assert.hpp>
+using namespace boost::container;
+
+//User-defined assertion to test throw_on_overflow
+struct throw_on_overflow_off
+{};
+
+namespace boost {
+ void assertion_failed(char const *, char const *, char const *, long)
+ {
+ throw throw_on_overflow_off();
+ }
+
+ void assertion_failed_msg(char const *, char const *, char const *, char const *, long )
+ {
+ throw throw_on_overflow_off();
+ }
+}
+
+void test_alignment()
+{
+ const std::size_t Capacity = 10u;
+ { //extended alignment
+ const std::size_t extended_alignment = sizeof(int)*4u;
+ BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of<int>::value);
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = static_vector_options_t< inplace_alignment<extended_alignment> >;
+ #else
+ typedef static_vector_options
+ < inplace_alignment<extended_alignment> >::type options_t;
+ #endif
+
+ static_vector<int, Capacity, options_t> v;
+ v.resize(v.capacity());
+ BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % extended_alignment) == 0);
+ }
+ { //default alignment
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = static_vector_options_t< inplace_alignment<0> >;
+ #else
+ typedef static_vector_options< inplace_alignment<0> >::type options_t;
+ #endif
+
+ static_vector<int, Capacity, options_t> v;
+ v.resize(v.capacity());
+ BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % dtl::alignment_of<int>::value) == 0);
+ }
+}
+
+void test_throw_on_overflow()
+{
+ #if !defined(BOOST_NO_EXCEPTIONS)
+ const std::size_t Capacity = 10u;
+ { //throw_on_overflow == true, expect bad_alloc
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = static_vector_options_t< throw_on_overflow<true> >;
+ #else
+ typedef static_vector_options
+ < throw_on_overflow<true> >::type options_t;
+ #endif
+
+ static_vector<int, Capacity, options_t> v;
+
+ v.resize(Capacity);
+ bool expected_type_thrown = false;
+ try{
+ v.push_back(0);
+ }
+ catch(std::bad_alloc&)
+ {
+ expected_type_thrown = true;
+ }
+ catch(...)
+ {}
+ BOOST_TEST(expected_type_thrown == true);
+ BOOST_TEST(v.capacity() == Capacity);
+ }
+ { //throw_on_overflow == false, test it through BOOST_ASSERT
+ //even in release mode (BOOST_ENABLE_ASSERT_HANDLER), and throwing
+ //a special type in that assertion.
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = static_vector_options_t< throw_on_overflow<false> >;
+ #else
+ typedef static_vector_options< throw_on_overflow<false> >::type options_t;
+ #endif
+
+ static_vector<int, Capacity, options_t> v;
+
+ v.resize(Capacity);
+ bool expected_type_thrown = false;
+ try{
+ v.push_back(0);
+ }
+ catch(throw_on_overflow_off)
+ {
+ expected_type_thrown = true;
+ }
+ catch(...)
+ {}
+ BOOST_TEST(expected_type_thrown == true);
+ BOOST_TEST(v.capacity() == Capacity);
+ }
+ #endif
+}
+
+int main()
+{
+ test_alignment();
+ test_throw_on_overflow();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/static_vector_test.cpp b/src/boost/libs/container/test/static_vector_test.cpp
new file mode 100644
index 000000000..f47df2e0c
--- /dev/null
+++ b/src/boost/libs/container/test/static_vector_test.cpp
@@ -0,0 +1,827 @@
+// Boost.Container static_vector
+// Unit Test
+
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2013 Andrew Hundt.
+
+// Use, modification and distribution is subject to 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)
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <vector>
+#include <list>
+
+#include "static_vector_test.hpp"
+
+
+template <typename T, size_t N>
+void test_ctor_ndc()
+{
+ static_vector<T, N> s;
+ BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+ BOOST_TEST_EQ(s.size() , 0u);
+ BOOST_TEST(s.capacity() == N);
+ BOOST_TEST(s.max_size() == N);
+ BOOST_TEST_THROWS( s.at(0u), std::out_of_range );
+}
+
+template <typename T, size_t N>
+void test_ctor_nc(size_t n)
+{
+ static_vector<T, N> s(n);
+ BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+ BOOST_TEST(s.max_size() == N);
+ BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ T val10(10);
+ s[0] = val10;
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ T val20(20);
+ s.at(1) = val20;
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_ctor_nd(size_t n, T const& v)
+{
+ static_vector<T, N> s(n, v);
+ BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+ BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ BOOST_TEST(v == s[0]);
+ BOOST_TEST(v == s.at(0));
+ BOOST_TEST(v == s[1]);
+ BOOST_TEST(v == s.at(1));
+ s[0] = T(10);
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
+}
+
+void test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ {
+ static_vector<int, 2> sv = {10, 8};
+ BOOST_TEST(10 == sv[0]);
+ BOOST_TEST(8 == sv[1]);
+
+ typedef static_vector<int, 1> sv_cap_1;
+ BOOST_TEST_THROWS(sv_cap_1({1, 1}), std::bad_alloc);
+ }
+
+ {
+ static_vector<int, 2> sv;
+ sv.assign({1, 2});
+ BOOST_TEST(1 == sv[0]);
+ BOOST_TEST(2 == sv[1]);
+
+ BOOST_TEST_THROWS(sv.assign({1, 2, 3}), std::bad_alloc);
+
+ static_vector<int, 3> greaterThanSv = {1, 2, 3};
+ BOOST_TEST_THROWS(sv = greaterThanSv, std::bad_alloc);
+ }
+
+ {
+ static_vector<int, 2> sv;
+ sv.insert(sv.begin(), {99, 95});
+ BOOST_TEST(99 == sv[0]);
+ BOOST_TEST(95 == sv[1]);
+
+ BOOST_TEST_THROWS(sv.insert(sv.begin(), {101, 102, 103}), std::bad_alloc);
+ }
+#endif
+}
+
+template <typename T, size_t N>
+void test_resize_nc(size_t n)
+{
+ static_vector<T, N> s;
+
+ s.resize(n);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+ BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ T val10(10);
+ s[0] = val10;
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ T val20(20);
+ s.at(1) = val20;
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_resize_nd(size_t n, T const& v)
+{
+ static_vector<T, N> s;
+
+ s.resize(n, v);
+ BOOST_TEST(s.size() == n);
+ BOOST_TEST(s.capacity() == N);
+ BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+ if ( 1 < n )
+ {
+ BOOST_TEST(v == s[0]);
+ BOOST_TEST(v == s.at(0));
+ BOOST_TEST(v == s[1]);
+ BOOST_TEST(v == s.at(1));
+ s[0] = T(10);
+ BOOST_TEST(T(10) == s[0]);
+ BOOST_TEST(T(10) == s.at(0));
+ s.at(1) = T(20);
+ BOOST_TEST(T(20) == s[1]);
+ BOOST_TEST(T(20) == s.at(1));
+ }
+}
+
+template <typename T, size_t N>
+void test_push_back_nd()
+{
+ static_vector<T, N> s;
+
+ BOOST_TEST(s.size() == 0);
+ BOOST_TEST_THROWS( s.at(0), std::out_of_range );
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ BOOST_TEST(s.size() == i + 1);
+ BOOST_TEST_THROWS( s.at(i + 1), std::out_of_range );
+ BOOST_TEST(T(i) == s.at(i));
+ BOOST_TEST(T(i) == s[i]);
+ BOOST_TEST(T(i) == s.back());
+ BOOST_TEST(T(0) == s.front());
+ BOOST_TEST(T(i) == *(s.data() + i));
+ }
+}
+
+template <typename T, size_t N>
+void test_pop_back_nd()
+{
+ static_vector<T, N> s;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ }
+
+ for ( size_t i = N ; i > 1 ; --i )
+ {
+ s.pop_back();
+ BOOST_TEST(s.size() == i - 1);
+ BOOST_TEST_THROWS( s.at(i - 1), std::out_of_range );
+ BOOST_TEST(T(i - 2) == s.at(i - 2));
+ BOOST_TEST(T(i - 2) == s[i - 2]);
+ BOOST_TEST(T(i - 2) == s.back());
+ BOOST_TEST(T(0) == s.front());
+ }
+}
+
+template <typename It1, typename It2>
+void test_compare_ranges(It1 first1, It1 last1, It2 first2, It2 last2)
+{
+ BOOST_TEST(boost::container::iterator_distance(first1, last1) == boost::container::iterator_distance(first2, last2));
+ for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2 )
+ BOOST_TEST(*first1 == *first2);
+}
+
+template <typename T, size_t N, typename C>
+void test_copy_and_assign(C const& c)
+{
+ {
+ static_vector<T, N> s(c.begin(), c.end());
+ BOOST_TEST(s.size() == c.size());
+ test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+ }
+ {
+ static_vector<T, N> s;
+ BOOST_TEST(0 == s.size());
+ s.assign(c.begin(), c.end());
+ BOOST_TEST(s.size() == c.size());
+ test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+ }
+}
+
+template <typename T, size_t N>
+void test_copy_and_assign_nd(T const& val)
+{
+ static_vector<T, N> s;
+ std::vector<T> v;
+ std::list<T> l;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ T t(i);
+ s.push_back(t);
+ v.push_back(t);
+ l.push_back(t);
+ }
+ // copy ctor
+ {
+ static_vector<T, N> s1(s);
+ BOOST_TEST(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+ // copy assignment
+ {
+ static_vector<T, N> s1;
+ BOOST_TEST(0 == s1.size());
+ s1 = s;
+ BOOST_TEST(s.size() == s1.size());
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ }
+
+ // ctor(Iter, Iter) and assign(Iter, Iter)
+ test_copy_and_assign<T, N>(s);
+ test_copy_and_assign<T, N>(v);
+ test_copy_and_assign<T, N>(l);
+
+ // assign(N, V)
+ {
+ static_vector<T, N> s1(s);
+ test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+ std::vector<T> a(N, val);
+ s1.assign(N, val);
+ test_compare_ranges(a.begin(), a.end(), s1.begin(), s1.end());
+ }
+
+ stable_vector<T> bsv(s.begin(), s.end());
+ vector<T> bv(s.begin(), s.end());
+ test_copy_and_assign<T, N>(bsv);
+ test_copy_and_assign<T, N>(bv);
+}
+
+template <typename T, size_t N>
+void test_iterators_nd()
+{
+ static_vector<T, N> s;
+ std::vector<T> v;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ s.push_back(T(i));
+ v.push_back(T(i));
+ }
+
+ test_compare_ranges(s.begin(), s.end(), v.begin(), v.end());
+ test_compare_ranges(s.rbegin(), s.rend(), v.rbegin(), v.rend());
+
+ s.assign(v.rbegin(), v.rend());
+
+ test_compare_ranges(s.begin(), s.end(), v.rbegin(), v.rend());
+ test_compare_ranges(s.rbegin(), s.rend(), v.begin(), v.end());
+}
+
+template <typename T, size_t N>
+void test_erase_nd()
+{
+ static_vector<T, N> s;
+ typedef typename static_vector<T, N>::iterator It;
+
+ for ( size_t i = 0 ; i < N ; ++i )
+ s.push_back(T(i));
+
+ // erase(pos)
+ {
+ for ( size_t i = 0 ; i < N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.erase(s1.begin() + i);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == N - 1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = i+1 ; j < N ; ++j )
+ BOOST_TEST(s1[j-1] == T(j));
+ }
+ }
+ // erase(first, last)
+ {
+ size_t n = N/3;
+ for ( size_t i = 0 ; i <= N ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ size_t removed = i + n < N ? n : N - i;
+ It it = s1.erase(s1.begin() + i, s1.begin() + i + removed);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == N - removed);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = i+n ; j < N ; ++j )
+ BOOST_TEST(s1[j-n] == T(j));
+ }
+ }
+}
+
+template <typename T, size_t N, typename SV, typename C>
+void test_insert(SV const& s, C const& c)
+{
+ size_t h = N/2;
+ size_t n = size_t(h/1.5f);
+
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+
+ typename C::const_iterator it = c.begin();
+ boost::container::iterator_advance(it, n);
+ typename static_vector<T, N>::iterator
+ it1 = s1.insert(s1.begin() + i, c.begin(), it);
+
+ BOOST_TEST(s1.begin() + i == it1);
+ BOOST_TEST(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_TEST(s1[j+i] == T(100 + j));
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+n] == T(j+i));
+ }
+}
+
+template <typename T, size_t N>
+void test_insert_nd(T const& val)
+{
+ size_t h = N/2;
+
+ static_vector<T, N> s, ss;
+ std::vector<T> v;
+ std::list<T> l;
+
+ typedef typename static_vector<T, N>::iterator It;
+
+ for ( size_t i = 0 ; i < h ; ++i )
+ {
+ s.push_back(T(i));
+ ss.push_back(T(100 + i));
+ v.push_back(T(100 + i));
+ l.push_back(T(100 + i));
+ }
+
+ // insert(pos, val)
+ {
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.insert(s1.begin() + i, val);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == h+1);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ BOOST_TEST(s1[i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+1] == T(j+i));
+ }
+ }
+ // insert(pos, n, val)
+ {
+ size_t n = size_t(h/1.5f);
+ for ( size_t i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> s1(s);
+ It it = s1.insert(s1.begin() + i, n, val);
+ BOOST_TEST(s1.begin() + i == it);
+ BOOST_TEST(s1.size() == h+n);
+ for ( size_t j = 0 ; j < i ; ++j )
+ BOOST_TEST(s1[j] == T(j));
+ for ( size_t j = 0 ; j < n ; ++j )
+ BOOST_TEST(s1[j+i] == val);
+ for ( size_t j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(s1[j+i+n] == T(j+i));
+ }
+ }
+ // insert(pos, first, last)
+ test_insert<T, N>(s, ss);
+ test_insert<T, N>(s, v);
+ test_insert<T, N>(s, l);
+
+ stable_vector<T> bsv(ss.begin(), ss.end());
+ vector<T> bv(ss.begin(), ss.end());
+ test_insert<T, N>(s, bv);
+ test_insert<T, N>(s, bsv);
+}
+
+template <typename T>
+void test_capacity_0_nd()
+{
+ static_vector<T, 10> v(5u, T(0));
+
+ static_vector<T, 0 > s;
+ BOOST_TEST(s.size() == 0);
+ BOOST_TEST(s.capacity() == 0);
+ BOOST_TEST_THROWS(s.at(0), std::out_of_range);
+ BOOST_TEST_THROWS(s.resize(5u, T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), 5u, T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc);
+ typedef static_vector<T, 0> static_vector_0_t;
+ BOOST_TEST_THROWS(static_vector_0_t s2(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(static_vector_0_t s1(5u, T(0)), std::bad_alloc);
+}
+
+template <typename T, size_t N>
+void test_exceptions_nd()
+{
+ static_vector<T, N> v(N, T(0));
+ static_vector<T, N/2> s(N/2, T(0));
+
+ BOOST_TEST_THROWS(s.resize(N, T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), 1, T(0)), std::bad_alloc);
+ BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(s.assign(N, T(0)), std::bad_alloc);
+ typedef static_vector<T, N/2> static_vector_n_half_t;
+ BOOST_TEST_THROWS(static_vector_n_half_t s2(v.begin(), v.end()), std::bad_alloc);
+ BOOST_TEST_THROWS(static_vector_n_half_t s1(N/2+1, T(0)), std::bad_alloc);
+}
+
+template <typename T, size_t N>
+void test_swap_and_move_nd()
+{
+ {
+ static_vector<T, N> v1, v2, v3, v4;
+ static_vector<T, N> s1, s2;
+ static_vector<T, N> s4;
+
+ for (size_t i = 0 ; i < N ; ++i )
+ {
+ v1.push_back(T(i));
+ v2.push_back(T(i));
+ v3.push_back(T(i));
+ v4.push_back(T(i));
+ }
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ s1.push_back(T(100 + i));
+ s2.push_back(T(100 + i));
+ s4.push_back(T(100 + i));
+ }
+
+ s1.swap(v1);
+ s2 = boost::move(v2);
+ static_vector<T, N> s3(boost::move(v3));
+ s4.swap(v4);
+
+ BOOST_TEST(v1.size() == N/2);
+ BOOST_TEST(s1.size() == N);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v2.size() == 0);
+ BOOST_TEST(s2.size() == N);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v3.size() == 0);
+ BOOST_TEST(s3.size() == N);
+ BOOST_TEST(v4.size() == N/2);
+ BOOST_TEST(s4.size() == N);
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ BOOST_TEST(v1[i] == T(100 + i));
+ BOOST_TEST(v4[i] == T(100 + i));
+ }
+ for (size_t i = 0 ; i < N ; ++i )
+ {
+ BOOST_TEST(s1[i] == T(i));
+ BOOST_TEST(s2[i] == T(i));
+ BOOST_TEST(s3[i] == T(i));
+ BOOST_TEST(s4[i] == T(i));
+ }
+ }
+ {
+ static_vector<T, N> v1, v2, v3;
+ static_vector<T, N/2> s1, s2, s3;
+
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ v1.push_back(T(i));
+ v2.push_back(T(i));
+ v3.push_back(T(i));
+ }
+ for (size_t i = 0 ; i < N/3 ; ++i )
+ {
+ s1.push_back(T(100 + i));
+ s2.push_back(T(100 + i));
+ }
+
+ s1.swap(v1);
+ s3 = v2;
+ s2 = boost::move(v2);
+ static_vector<T, N/2> s4(boost::move(v3));
+
+ BOOST_TEST(v1.size() == N/3);
+ BOOST_TEST(s1.size() == N/2);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v2.size() == 0);
+ BOOST_TEST(s2.size() == N/2);
+ BOOST_TEST(s3.size() == N/2);
+ //iG moving does not imply emptying source
+ //BOOST_TEST(v3.size() == 0);
+ BOOST_TEST(s4.size() == N/2);
+ for (size_t i = 0 ; i < N/3 ; ++i )
+ BOOST_TEST(v1[i] == T(100 + i));
+ for (size_t i = 0 ; i < N/2 ; ++i )
+ {
+ BOOST_TEST(s1[i] == T(i));
+ BOOST_TEST(s2[i] == T(i));
+ BOOST_TEST(s3[i] == T(i));
+ BOOST_TEST(s4[i] == T(i));
+ }
+ }
+ {
+ typedef static_vector<T, N/2> small_vector_t;
+ static_vector<T, N> v(N, T(0));
+ small_vector_t s(N/2, T(1));
+ BOOST_TEST_THROWS(s.swap(v), std::bad_alloc);
+ v.resize(N, T(0));
+ BOOST_TEST_THROWS(s = boost::move(v), std::bad_alloc);
+ BOOST_TEST_THROWS(s = v, std::bad_alloc);
+ v.resize(N, T(0));
+ BOOST_TEST_THROWS(small_vector_t s2(boost::move(v)), std::bad_alloc);
+ }
+}
+
+template <typename T, size_t N>
+void test_emplace_0p()
+{
+ //emplace_back()
+ {
+ static_vector<T, N> v;
+
+ for (int i = 0 ; i < int(N) ; ++i )
+ v.emplace_back();
+ BOOST_TEST(v.size() == N);
+ BOOST_TEST_THROWS(v.emplace_back(), std::bad_alloc);
+ }
+}
+
+template <typename T, size_t N>
+void test_emplace_2p()
+{
+ //emplace_back(pos, int, int)
+ {
+ static_vector<T, N> v;
+
+ for (int i = 0 ; i < int(N) ; ++i )
+ v.emplace_back(i, 100 + i);
+ BOOST_TEST(v.size() == N);
+ BOOST_TEST_THROWS(v.emplace_back(N, 100 + N), std::bad_alloc);
+ BOOST_TEST(v.size() == N);
+ for (int i = 0 ; i < int(N) ; ++i )
+ BOOST_TEST(v[i] == T(i, 100 + i));
+ }
+
+ // emplace(pos, int, int)
+ {
+ typedef typename static_vector<T, N>::iterator It;
+
+ int h = N / 2;
+
+ static_vector<T, N> v;
+ for ( int i = 0 ; i < h ; ++i )
+ v.emplace_back(i, 100 + i);
+
+ for ( int i = 0 ; i <= h ; ++i )
+ {
+ static_vector<T, N> vv(v);
+ It it = vv.emplace(vv.begin() + i, i+100, i+200);
+ BOOST_TEST(vv.begin() + i == it);
+ BOOST_TEST(vv.size() == size_t(h+1));
+ for ( int j = 0 ; j < i ; ++j )
+ BOOST_TEST(vv[j] == T(j, j+100));
+ BOOST_TEST(vv[i] == T(i+100, i+200));
+ for ( int j = 0 ; j < h-i ; ++j )
+ BOOST_TEST(vv[j+i+1] == T(j+i, j+i+100));
+ }
+ }
+}
+
+template <typename T, size_t N>
+void test_sv_elem(T const& t)
+{
+ typedef static_vector<T, N> V;
+
+ static_vector<V, N> v;
+
+ v.push_back(V(N/2, t));
+ V vvv(N/2, t);
+ v.push_back(boost::move(vvv));
+ v.insert(v.begin(), V(N/2, t));
+ v.insert(v.end(), V(N/2, t));
+ v.emplace_back(N/2, t);
+}
+
+bool default_init_test()//Test for default initialization
+{
+ const std::size_t Capacity = 100;
+
+ typedef static_vector<int, Capacity> di_vector_t;
+
+ {
+ di_vector_t v(Capacity, default_init);
+ }
+ {
+ di_vector_t v;
+ int *p = v.data();
+
+ for(std::size_t i = 0; i != Capacity; ++i, ++p){
+ *p = static_cast<int>(i);
+ }
+
+ //Destroy the vector, p still pointing to the storage
+ v.~di_vector_t();
+
+ di_vector_t &rv = *::new(&v)di_vector_t(Capacity, default_init);
+ di_vector_t::iterator it = rv.begin();
+
+ for(std::size_t i = 0; i != Capacity; ++i, ++it){
+ if(*it != static_cast<int>(i))
+ return false;
+ }
+
+ v.~di_vector_t();
+ }
+ {
+ di_vector_t v;
+
+ int *p = v.data();
+ for(std::size_t i = 0; i != Capacity; ++i, ++p){
+ *p = static_cast<int>(i+100);
+ }
+
+ v.resize(Capacity, default_init);
+
+ di_vector_t::iterator it = v.begin();
+ for(std::size_t i = 0; i != Capacity; ++i, ++it){
+ if(*it != static_cast<int>(i+100))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+int main(int, char* [])
+{
+ using boost::container::test::movable_and_copyable_int;
+ using boost::container::test::produce_movable_and_copyable_int;
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_ctor_ndc<int, 10>();
+ test_ctor_ndc<value_ndc, 10>();
+ test_ctor_ndc<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_ndc<shptr_value, 10>();
+ test_ctor_ndc<movable_and_copyable_int, 10>();
+
+ test_ctor_nc<int, 10>(5);
+ test_ctor_nc<value_nc, 10>(5);
+ test_ctor_nc<counting_value, 10>(5);
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_nc<shptr_value, 10>(5);
+ test_ctor_nc<movable_and_copyable_int, 10>(5);
+
+ test_ctor_nd<int, 10>(5, 1);
+ test_ctor_nd<value_nd, 10>(5, value_nd(1));
+ test_ctor_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_ctor_nd<shptr_value, 10>(5, shptr_value(1));
+ test_ctor_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+ test_resize_nc<int, 10>(5);
+ test_resize_nc<value_nc, 10>(5);
+ test_resize_nc<counting_value, 10>(5);
+ BOOST_TEST(counting_value::count() == 0);
+ test_resize_nc<shptr_value, 10>(5);
+ test_resize_nc<movable_and_copyable_int, 10>(5);
+
+ test_resize_nd<int, 10>(5, 1);
+ test_resize_nd<value_nd, 10>(5, value_nd(1));
+ test_resize_nd<counting_value, 10>(5, counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_resize_nd<shptr_value, 10>(5, shptr_value(1));
+ test_resize_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+ test_push_back_nd<int, 10>();
+ test_push_back_nd<value_nd, 10>();
+ test_push_back_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_push_back_nd<shptr_value, 10>();
+ test_push_back_nd<movable_and_copyable_int, 10>();
+
+ test_pop_back_nd<int, 10>();
+ test_pop_back_nd<value_nd, 10>();
+ test_pop_back_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_pop_back_nd<shptr_value, 10>();
+ test_pop_back_nd<movable_and_copyable_int, 10>();
+
+ test_copy_and_assign_nd<int, 10>(1);
+ test_copy_and_assign_nd<value_nd, 10>(value_nd(1));
+ test_copy_and_assign_nd<counting_value, 10>(counting_value(1));
+ BOOST_TEST(counting_value::count() == 0);
+ test_copy_and_assign_nd<shptr_value, 10>(shptr_value(1));
+ test_copy_and_assign_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+ test_iterators_nd<int, 10>();
+ test_iterators_nd<value_nd, 10>();
+ test_iterators_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_iterators_nd<shptr_value, 10>();
+ test_iterators_nd<movable_and_copyable_int, 10>();
+
+ test_erase_nd<int, 10>();
+ test_erase_nd<value_nd, 10>();
+ test_erase_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_erase_nd<shptr_value, 10>();
+ test_erase_nd<movable_and_copyable_int, 10>();
+
+ test_insert_nd<int, 10>(50);
+ test_insert_nd<value_nd, 10>(value_nd(50));
+ test_insert_nd<counting_value, 10>(counting_value(50));
+ BOOST_TEST(counting_value::count() == 0);
+ test_insert_nd<shptr_value, 10>(shptr_value(50));
+ test_insert_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+ test_capacity_0_nd<int>();
+ test_capacity_0_nd<value_nd>();
+ test_capacity_0_nd<counting_value>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_capacity_0_nd<shptr_value>();
+ test_capacity_0_nd<movable_and_copyable_int>();
+
+ test_exceptions_nd<int, 10>();
+ test_exceptions_nd<value_nd, 10>();
+ test_exceptions_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_exceptions_nd<shptr_value, 10>();
+ test_exceptions_nd<movable_and_copyable_int, 10>();
+
+ test_swap_and_move_nd<int, 10>();
+ test_swap_and_move_nd<value_nd, 10>();
+ test_swap_and_move_nd<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+ test_swap_and_move_nd<shptr_value, 10>();
+ test_swap_and_move_nd<movable_and_copyable_int, 10>();
+
+ test_emplace_0p<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_emplace_2p<counting_value, 10>();
+ BOOST_TEST(counting_value::count() == 0);
+
+ test_sv_elem<int, 10>(50);
+ test_sv_elem<value_nd, 10>(value_nd(50));
+ test_sv_elem<counting_value, 10>(counting_value(50));
+ BOOST_TEST(counting_value::count() == 0);
+ test_sv_elem<shptr_value, 10>(shptr_value(50));
+ test_sv_elem<movable_and_copyable_int, 10>(movable_and_copyable_int(50));
+
+ BOOST_TEST(default_init_test() == true);
+
+ test_support_for_initializer_list();
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::static_vector<int, 3> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ }
+
+ return boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/static_vector_test.hpp b/src/boost/libs/container/test/static_vector_test.hpp
new file mode 100644
index 000000000..ab931b274
--- /dev/null
+++ b/src/boost/libs/container/test/static_vector_test.hpp
@@ -0,0 +1,103 @@
+// Boost.Container static_vector
+// Unit Test
+
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2013 Andrew Hundt.
+
+// Use, modification and distribution is subject to 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)
+
+#ifndef BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
+#define BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
+
+#include <boost/container/static_vector.hpp>
+
+#define BOOST_SP_DISABLE_THREADS
+#include <boost/shared_ptr.hpp>
+#include "movable_int.hpp"
+
+using namespace boost::container;
+
+class value_ndc
+{
+public:
+ explicit value_ndc(int a) : aa(a) {}
+ ~value_ndc() {}
+ bool operator==(value_ndc const& v) const { return aa == v.aa; }
+ bool operator<(value_ndc const& v) const { return aa < v.aa; }
+private:
+ value_ndc(value_ndc const&) {}
+ value_ndc & operator=(value_ndc const&) { return *this; }
+ int aa;
+};
+
+class value_nd
+{
+public:
+ explicit value_nd(int a) : aa(a) {}
+ ~value_nd() {}
+ bool operator==(value_nd const& v) const { return aa == v.aa; }
+ bool operator<(value_nd const& v) const { return aa < v.aa; }
+private:
+ int aa;
+};
+
+class value_nc
+{
+public:
+ explicit value_nc(int a = 0) : aa(a) {}
+ ~value_nc() {}
+ bool operator==(value_nc const& v) const { return aa == v.aa; }
+ bool operator<(value_nc const& v) const { return aa < v.aa; }
+private:
+ value_nc(value_nc const&) {}
+ value_nc & operator=(value_ndc const&) { return *this; }
+ int aa;
+};
+
+class counting_value
+{
+ BOOST_COPYABLE_AND_MOVABLE(counting_value)
+
+public:
+ explicit counting_value(int a = 0, int b = 0) : aa(a), bb(b) { ++c(); }
+ counting_value(counting_value const& v) : aa(v.aa), bb(v.bb) { ++c(); }
+ counting_value(BOOST_RV_REF(counting_value) p) : aa(p.aa), bb(p.bb) { p.aa = 0; p.bb = 0; ++c(); } // Move constructor
+ counting_value& operator=(BOOST_RV_REF(counting_value) p) { aa = p.aa; p.aa = 0; bb = p.bb; p.bb = 0; return *this; } // Move assignment
+ counting_value& operator=(BOOST_COPY_ASSIGN_REF(counting_value) p) { aa = p.aa; bb = p.bb; return *this; } // Copy assignment
+ ~counting_value() { --c(); }
+ bool operator==(counting_value const& v) const { return aa == v.aa && bb == v.bb; }
+ bool operator<(counting_value const& v) const { return aa < v.aa || ( aa == v.aa && bb < v.bb ); }
+ static size_t count() { return c(); }
+
+private:
+ static size_t & c() { static size_t co = 0; return co; }
+ int aa, bb;
+};
+
+namespace boost {
+
+template <class T>
+struct has_nothrow_move;
+
+template <>
+struct has_nothrow_move<counting_value>
+{
+ static const bool value = true;
+};
+
+}
+
+class shptr_value
+{
+ typedef boost::shared_ptr<int> Ptr;
+public:
+ explicit shptr_value(int a = 0) : m_ptr(new int(a)) {}
+ bool operator==(shptr_value const& v) const { return *m_ptr == *(v.m_ptr); }
+ bool operator<(shptr_value const& v) const { return *m_ptr < *(v.m_ptr); }
+private:
+ boost::shared_ptr<int> m_ptr;
+};
+
+#endif // BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
diff --git a/src/boost/libs/container/test/string_test.cpp b/src/boost/libs/container/test/string_test.cpp
new file mode 100644
index 000000000..b2d17f6aa
--- /dev/null
+++ b/src/boost/libs/container/test/string_test.cpp
@@ -0,0 +1,596 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/string.hpp>
+#include <string>
+#include <vector>
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include <cstring>
+#include <cstdio>
+#include <cstddef>
+#include <new>
+#include "dummy_test_allocator.hpp"
+#include "check_equal_containers.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "propagate_allocator_test.hpp"
+#include "default_init_test.hpp"
+#include "comparison_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+#include <boost/utility/string_view.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+struct StringEqual
+{
+ template<class Str1, class Str2>
+ bool operator ()(const Str1 &string1, const Str2 &string2) const
+ {
+ if(string1.size() != string2.size())
+ return false;
+ return std::char_traits<typename Str1::value_type>::compare
+ (string1.c_str(), string2.c_str(), string1.size()) == 0;
+ }
+};
+
+//Function to check if both lists are equal
+template<class StrVector1, class StrVector2>
+bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2)
+{
+ StringEqual comp;
+ return boost::container::algo_equal(strvect1->begin(), strvect1->end(),
+ strvect2->begin(), comp);
+}
+
+template<class ForwardIt>
+ForwardIt unique(ForwardIt first, ForwardIt const last)
+{
+ if(first == last){
+ ForwardIt i = first;
+ //Find first adjacent pair
+ while(1){
+ if(++i == last){
+ return last;
+ }
+ else if(*first == *i){
+ break;
+ }
+ ++first;
+ }
+ //Now overwrite skipping adjacent elements
+ while (++i != last) {
+ if (!(*first == *i)) {
+ *(++first) = boost::move(*i);
+ }
+ }
+ ++first;
+ }
+ return first;
+}
+
+template<class CharType>
+struct string_literals;
+
+template<>
+struct string_literals<char>
+{
+ static const char *String()
+ { return "String"; }
+ static const char *Prefix()
+ { return "Prefix"; }
+ static const char *Suffix()
+ { return "Suffix"; }
+ static const char *LongString()
+ { return "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
+ static char Char()
+ { return 'C'; }
+ static void sprintf_number(char *buf, int number)
+ {
+ std::sprintf(buf, "%i", number);
+ }
+};
+
+template<>
+struct string_literals<wchar_t>
+{
+ static const wchar_t *String()
+ { return L"String"; }
+ static const wchar_t *Prefix()
+ { return L"Prefix"; }
+ static const wchar_t *Suffix()
+ { return L"Suffix"; }
+ static const wchar_t *LongString()
+ { return L"LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
+ static wchar_t Char()
+ { return L'C'; }
+ static void sprintf_number(wchar_t *buffer, unsigned int number)
+ {
+ //For compilers without wsprintf, print it backwards
+ const wchar_t *digits = L"0123456789";
+ wchar_t *buf = buffer;
+
+ while(1){
+ int rem = number % 10;
+ number = number / 10;
+
+ *buf = digits[rem];
+ ++buf;
+ if(!number){
+ *buf = 0;
+ break;
+ }
+ }
+
+ }
+};
+
+template<class CharType>
+int string_test()
+{
+ typedef std::basic_string<CharType> StdString;
+ typedef vector<StdString> StdStringVector;
+ typedef basic_string<CharType> BoostString;
+ typedef vector<BoostString> BoostStringVector;
+
+ const int MaxSize = 100;
+
+ {
+ BoostStringVector *boostStringVect = new BoostStringVector;
+ StdStringVector *stdStringVect = new StdStringVector;
+ BoostString auxBoostString;
+ StdString auxStdString(StdString(auxBoostString.begin(), auxBoostString.end() ));
+
+ CharType buffer [20];
+
+ //First, push back
+ for(int i = 0; i < MaxSize; ++i){
+ auxBoostString = string_literals<CharType>::String();
+ auxStdString = string_literals<CharType>::String();
+ string_literals<CharType>::sprintf_number(buffer, i);
+ auxBoostString += buffer;
+ auxStdString += buffer;
+ boostStringVect->push_back(auxBoostString);
+ stdStringVect->push_back(auxStdString);
+ }
+
+ if(auxBoostString.data() != const_cast<const BoostString&>(auxBoostString).data() &&
+ auxBoostString.data() != &auxBoostString[0])
+ return 1;
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+ return 1;
+ }
+
+ //Now push back moving
+ for(int i = 0; i < MaxSize; ++i){
+ auxBoostString = string_literals<CharType>::String();
+ auxStdString = string_literals<CharType>::String();
+ string_literals<CharType>::sprintf_number(buffer, i);
+ auxBoostString += buffer;
+ auxStdString += buffer;
+ boostStringVect->push_back(boost::move(auxBoostString));
+ stdStringVect->push_back(auxStdString);
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+ return 1;
+ }
+
+ //push front
+ for(int i = 0; i < MaxSize; ++i){
+ auxBoostString = string_literals<CharType>::String();
+ auxStdString = string_literals<CharType>::String();
+ string_literals<CharType>::sprintf_number(buffer, i);
+ auxBoostString += buffer;
+ auxStdString += buffer;
+ boostStringVect->insert(boostStringVect->begin(), auxBoostString);
+ stdStringVect->insert(stdStringVect->begin(), auxStdString);
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+ return 1;
+ }
+
+ //Now push front moving
+ for(int i = 0; i < MaxSize; ++i){
+ auxBoostString = string_literals<CharType>::String();
+ auxStdString = string_literals<CharType>::String();
+ string_literals<CharType>::sprintf_number(buffer, i);
+ auxBoostString += buffer;
+ auxStdString += buffer;
+ boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString));
+ stdStringVect->insert(stdStringVect->begin(), auxStdString);
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+ return 1;
+ }
+
+ //Now test long and short representation swapping
+
+ //Short first
+ auxBoostString = string_literals<CharType>::String();
+ auxStdString = string_literals<CharType>::String();
+ BoostString boost_swapper;
+ StdString std_swapper;
+ boost_swapper.swap(auxBoostString);
+ std_swapper.swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+ if(!StringEqual()(boost_swapper, std_swapper))
+ return 1;
+ boost_swapper.swap(auxBoostString);
+ std_swapper.swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+ if(!StringEqual()(boost_swapper, std_swapper))
+ return 1;
+
+ //Shrink_to_fit
+ auxBoostString.shrink_to_fit();
+ StdString(auxStdString).swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+
+ //Reserve + shrink_to_fit
+ auxBoostString.reserve(boost_swapper.size()*2+1);
+ auxStdString.reserve(std_swapper.size()*2+1);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+
+ auxBoostString.shrink_to_fit();
+ StdString(auxStdString).swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+
+ //Long string
+ auxBoostString = string_literals<CharType>::LongString();
+ auxStdString = string_literals<CharType>::LongString();
+ boost_swapper = BoostString();
+ std_swapper = StdString();
+ boost_swapper.swap(auxBoostString);
+ std_swapper.swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+ if(!StringEqual()(boost_swapper, std_swapper))
+ return 1;
+ boost_swapper.swap(auxBoostString);
+ std_swapper.swap(auxStdString);
+
+ //Shrink_to_fit
+ auxBoostString.shrink_to_fit();
+ StdString(auxStdString).swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+
+ auxBoostString.clear();
+ auxStdString.clear();
+ auxBoostString.shrink_to_fit();
+ StdString(auxStdString).swap(auxStdString);
+ if(!StringEqual()(auxBoostString, auxStdString))
+ return 1;
+
+ //No sort
+ std::sort(boostStringVect->begin(), boostStringVect->end());
+ std::sort(stdStringVect->begin(), stdStringVect->end());
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ const CharType *prefix = string_literals<CharType>::Prefix();
+ const int prefix_size = std::char_traits<CharType>::length(prefix);
+ const CharType *sufix = string_literals<CharType>::Suffix();
+
+ for(int i = 0; i < MaxSize; ++i){
+ (*boostStringVect)[i].append(sufix);
+ (*stdStringVect)[i].append(sufix);
+ (*boostStringVect)[i].insert((*boostStringVect)[i].begin(),
+ prefix, prefix + prefix_size);
+ (*stdStringVect)[i].insert((*stdStringVect)[i].begin(),
+ prefix, prefix + prefix_size);
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ for(int i = 0; i < MaxSize; ++i){
+ std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
+ std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ for(int i = 0; i < MaxSize; ++i){
+ std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
+ std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ for(int i = 0; i < MaxSize; ++i){
+ std::sort(boostStringVect->begin(), boostStringVect->end());
+ std::sort(stdStringVect->begin(), stdStringVect->end());
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ for(int i = 0; i < MaxSize; ++i){
+ (*boostStringVect)[i].replace((*boostStringVect)[i].begin(),
+ (*boostStringVect)[i].end(),
+ string_literals<CharType>::String());
+ (*stdStringVect)[i].replace((*stdStringVect)[i].begin(),
+ (*stdStringVect)[i].end(),
+ string_literals<CharType>::String());
+ }
+
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ boostStringVect->erase(::unique(boostStringVect->begin(), boostStringVect->end()),
+ boostStringVect->end());
+ stdStringVect->erase(::unique(stdStringVect->begin(), stdStringVect->end()),
+ stdStringVect->end());
+ if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+ //Check addition
+ {
+ BoostString bs2 = string_literals<CharType>::String();
+ StdString ss2 = string_literals<CharType>::String();
+ BoostString bs3 = string_literals<CharType>::Suffix();
+ StdString ss3 = string_literals<CharType>::Suffix();
+ BoostString bs4 = bs2 + bs3;
+ StdString ss4 = ss2 + ss3;
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs4 = bs2 + BoostString();
+ ss4 = ss2 + StdString();
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs4 = BoostString() + bs2;
+ ss4 = StdString() + ss2;
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs4 = BoostString() + boost::move(bs2);
+ ss4 = StdString() + boost::move(ss2);
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = boost::move(bs2) + BoostString();
+ ss4 = boost::move(ss2) + StdString();
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = string_literals<CharType>::Prefix() + boost::move(bs2);
+ ss4 = string_literals<CharType>::Prefix() + boost::move(ss2);
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = boost::move(bs2) + string_literals<CharType>::Suffix();
+ ss4 = boost::move(ss2) + string_literals<CharType>::Suffix();
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = string_literals<CharType>::Prefix() + bs2;
+ ss4 = string_literals<CharType>::Prefix() + ss2;
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = bs2 + string_literals<CharType>::Suffix();
+ ss4 = ss2 + string_literals<CharType>::Suffix();
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = string_literals<CharType>::Char() + bs2;
+ ss4 = string_literals<CharType>::Char() + ss2;
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ bs2 = string_literals<CharType>::String();
+ ss2 = string_literals<CharType>::String();
+ bs4 = bs2 + string_literals<CharType>::Char();
+ ss4 = ss2 + string_literals<CharType>::Char();
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ //Check front/back/begin/end
+
+ if(bs4.front() != *ss4.begin())
+ return 1;
+
+ if(bs4.back() != *(ss4.end()-1))
+ return 1;
+
+ bs4.pop_back();
+ ss4.erase(ss4.end()-1);
+ if(!StringEqual()(bs4, ss4)){
+ return 1;
+ }
+
+ if(*bs4.begin() != *ss4.begin())
+ return 1;
+ if(*bs4.cbegin() != *ss4.begin())
+ return 1;
+ if(*bs4.rbegin() != *ss4.rbegin())
+ return 1;
+ if(*bs4.crbegin() != *ss4.rbegin())
+ return 1;
+ if(*(bs4.end()-1) != *(ss4.end()-1))
+ return 1;
+ if(*(bs4.cend()-1) != *(ss4.end()-1))
+ return 1;
+ if(*(bs4.rend()-1) != *(ss4.rend()-1))
+ return 1;
+ if(*(bs4.crend()-1) != *(ss4.rend()-1))
+ return 1;
+ }
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ //Chect Constructor Template Auto Deduction
+ {
+ auto gold = StdString(string_literals<CharType>::String());
+ auto test = basic_string(gold.begin(), gold.end());
+ if(!StringEqual()(gold, test)) {
+ return 1;
+ }
+ }
+#endif
+
+
+ //When done, delete vector
+ delete boostStringVect;
+ delete stdStringVect;
+ }
+ return 0;
+}
+
+bool test_expand_bwd()
+{
+ //Now test all back insertion possibilities
+ typedef test::expand_bwd_test_allocator<char>
+ allocator_type;
+ typedef basic_string<char, std::char_traits<char>, allocator_type>
+ string_type;
+ return test::test_all_expand_bwd<string_type>();
+}
+
+struct boost_container_string;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_string>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::basic_string<T, std::char_traits<T>, Allocator> type;
+ };
+};
+
+
+}}} //namespace boost::container::test
+
+
+int main()
+{
+ if(string_test<char>()){
+ return 1;
+ }
+
+ if(string_test<wchar_t>()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Backwards expansion test
+ ////////////////////////////////////
+ if(!test_expand_bwd())
+ return 1;
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_string>())
+ return 1;
+
+ ////////////////////////////////////
+ // Default init test
+ ////////////////////////////////////
+ if(!test::default_init_test< basic_string<char, std::char_traits<char>, test::default_init_allocator<char> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ if(!test::default_init_test< basic_string<wchar_t, std::char_traits<wchar_t>, test::default_init_allocator<wchar_t> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::basic_string<char> cont_int;
+ cont_int a; a.push_back(char(1)); a.push_back(char(2)); a.push_back(char(3));
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ }
+ {
+ typedef boost::container::basic_string<wchar_t> cont_int;
+ cont_int a; a.push_back(wchar_t(1)); a.push_back(wchar_t(2)); a.push_back(wchar_t(3));
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ }
+
+ ////////////////////////////////////
+ // Comparison testing
+ ////////////////////////////////////
+ {
+ if(!boost::container::test::test_container_comparisons<string>())
+ return 1;
+ if(!boost::container::test::test_container_comparisons<wstring>())
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::basic_string<char> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::basic_string<char, std::char_traits<char>, std::allocator<char> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/string_view_compat_test.cpp b/src/boost/libs/container/test/string_view_compat_test.cpp
new file mode 100644
index 000000000..f786b96c2
--- /dev/null
+++ b/src/boost/libs/container/test/string_view_compat_test.cpp
@@ -0,0 +1,275 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2017. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/string.hpp>
+#include <boost/utility/string_view.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+void conversion_test()
+{
+ #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+ {
+ const boost::container::string s = "some text";
+ boost::string_view sv(s);
+ BOOST_TEST(s.data() == sv.data() && s.size() == sv.size());
+ boost::string_view sv2;
+ sv2 = s;
+ BOOST_TEST(s.data() == sv2.data() && s.size() == sv2.size());
+ const boost::string_view csv(s);
+ BOOST_TEST(s.data() == sv.data() && s.size() == csv.size());
+ }
+ #endif
+}
+
+void to_view_test()
+{
+ const boost::container::string s = "some text";
+ boost::string_view sv(s.to_view<boost::string_view>());
+ BOOST_TEST(s.data() == sv.data() && s.size() == sv.size());
+ boost::string_view sv2;
+ sv2 = s.to_view<boost::string_view>();
+ BOOST_TEST(s.data() == sv2.data() && s.size() == sv2.size());
+ const boost::string_view csv(s.to_view<boost::string_view>());
+ BOOST_TEST(s.data() == csv.data() && s.size() == csv.size());
+}
+
+void equal_test()
+{
+ const boost::string_view sv = "same text";
+ const boost::string_view svd = "different text";
+ const boost::container::string s = "same text";
+ BOOST_TEST(sv == s);
+ BOOST_TEST(s == sv);
+ BOOST_TEST(!(svd == s));
+ BOOST_TEST(!(s == svd));
+}
+
+void unequal_test()
+{
+ const boost::string_view sv = "same text";
+ const boost::string_view svd = "different text";
+ const boost::container::string s = "same text";
+ BOOST_TEST(!(sv != s));
+ BOOST_TEST(!(s != sv));
+ BOOST_TEST(svd != s);
+ BOOST_TEST(s != svd);
+}
+
+void less_test()
+{
+ boost::string_view sv = "0123456";
+ boost::container::string s = "0123459";
+ BOOST_TEST(sv < s);
+ BOOST_TEST(!(s < sv));
+
+ sv = "0123459";
+ s = "0123456";
+ BOOST_TEST(!(sv < s));
+ BOOST_TEST(s < sv);
+
+ sv = "0123456";
+ BOOST_TEST(!(sv < s));
+ BOOST_TEST(!(s < sv));
+}
+
+void greater_test()
+{
+ boost::string_view sv = "0123459";
+ boost::container::string s = "0123456";
+ BOOST_TEST(sv > s);
+ BOOST_TEST(!(s > sv));
+
+ sv = "0123456";
+ s = "0123459";
+ BOOST_TEST(!(sv > s));
+ BOOST_TEST(s > sv);
+
+ sv = "0123459";
+ BOOST_TEST(!(sv > s));
+ BOOST_TEST(!(s > sv));
+}
+
+void less_equal_test()
+{
+ boost::string_view sv = "0123456";
+ boost::container::string s = "0123459";
+ BOOST_TEST(sv <= s);
+ BOOST_TEST(!(s <= sv));
+
+ sv = "0123459";
+ s = "0123456";
+ BOOST_TEST(!(sv <= s));
+ BOOST_TEST(s <= sv);
+
+ sv = "0123456";
+ BOOST_TEST(sv <= s);
+ BOOST_TEST(s <= sv);
+}
+
+void greater_equal_test()
+{
+ boost::string_view sv = "0123459";
+ boost::container::string s = "0123456";
+ BOOST_TEST(sv >= s);
+ BOOST_TEST(!(s >= sv));
+
+ sv = "0123456";
+ s = "0123459";
+ BOOST_TEST(!(sv >= s));
+ BOOST_TEST(s >= sv);
+
+ sv = "0123459";
+ BOOST_TEST(sv >= s);
+ BOOST_TEST(s >= sv);
+}
+
+void constructor_test()
+{
+ boost::string_view sv = "0123459";
+ boost::container::string s(sv);
+ BOOST_TEST(sv == s);
+ boost::container::string s2(sv, s.get_allocator());
+ BOOST_TEST(sv == s);
+}
+
+void assignment_test()
+{
+ boost::string_view sv = "0123459";
+ boost::container::string s;
+ s = sv;
+ BOOST_TEST(sv == s);
+}
+
+void assign_test()
+{
+ boost::string_view sv = "0123459";
+ boost::container::string s;
+ s.assign(sv);
+ BOOST_TEST(sv == s);
+}
+
+void plus_equal_test()
+{
+ boost::string_view sv = "23459";
+ boost::container::string s("01");
+ s += sv;
+ BOOST_TEST(s == "0123459");
+}
+
+void append_test()
+{
+ boost::string_view sv = "23459";
+ boost::container::string s("01");
+ s.append(sv);
+ BOOST_TEST(s == "0123459");
+}
+
+void insert_test()
+{
+ boost::string_view sv = "34";
+ boost::container::string s("01259");
+ s.insert(3u, sv);
+ BOOST_TEST(s == "0123459");
+}
+
+void replace_test()
+{
+ boost::string_view sv = "5678";
+ boost::container::string s("01259");
+ s.replace(2u, 2u, sv);
+ BOOST_TEST(s == "0156789");
+ s.replace(s.begin()+3, s.begin()+6, sv);
+ BOOST_TEST(s == "01556789");
+ s.replace(5u, 3u, sv, 2u, 2u);
+ BOOST_TEST(s == "0155678");
+}
+
+void find_test()
+{
+ const boost::string_view sv = "25";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.find(sv,4) == 5);
+}
+
+void rfind_test()
+{
+ const boost::string_view sv = "25";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.rfind(sv,4) == 2);
+}
+
+void find_first_of_test()
+{
+ const boost::string_view sv = "52";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.find_first_of(sv,4) == 5);
+}
+
+void find_last_of_test()
+{
+ const boost::string_view sv = "52";
+ boost::container::string s("520125925123");
+ BOOST_TEST(s.find_last_of(sv,6) == 5);
+}
+
+void find_first_not_of_test()
+{
+ const boost::string_view sv = "52";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.find_first_not_of(sv,2) == 4);
+}
+
+void find_last_not_of_test()
+{
+ const boost::string_view sv = "52";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.find_last_not_of(sv,6) == 4);
+}
+
+void compare_test()
+{
+ const boost::string_view sv = "52";
+ boost::container::string s("0125925123");
+ BOOST_TEST(s.compare(sv) < 0);
+ BOOST_TEST(s.compare(boost::string_view("0125925123")) == 0);
+ BOOST_TEST(s.compare(2u, s.size() - 2u, boost::string_view("25925123")) == 0);
+ boost::string_view sv2("5212592512389");
+ BOOST_TEST(s.compare(2u, s.size() - 2u, sv2, 3, sv2.size()-5u) == 0);
+}
+
+int main()
+{
+ conversion_test();
+ to_view_test();
+ equal_test();
+ unequal_test();
+ less_test();
+ greater_test();
+ less_equal_test();
+ greater_equal_test();
+ constructor_test();
+ assignment_test();
+ assign_test();
+ plus_equal_test();
+ append_test();
+ insert_test();
+ replace_test();
+ find_test();
+ rfind_test();
+ find_first_of_test();
+ find_last_of_test();
+ find_first_not_of_test();
+ find_last_not_of_test();
+ compare_test();
+
+ return boost::report_errors();
+}
+
diff --git a/src/boost/libs/container/test/synchronized_pool_resource_test.cpp b/src/boost/libs/container/test/synchronized_pool_resource_test.cpp
new file mode 100644
index 000000000..da1589a06
--- /dev/null
+++ b/src/boost/libs/container/test/synchronized_pool_resource_test.cpp
@@ -0,0 +1,19 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/synchronized_pool_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "pool_resource_test.hpp"
+
+int main()
+{
+ test_pool_resource<boost::container::pmr::synchronized_pool_resource>();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/throw_exception_test.cpp b/src/boost/libs/container/test/throw_exception_test.cpp
new file mode 100644
index 000000000..2cbabefcc
--- /dev/null
+++ b/src/boost/libs/container/test/throw_exception_test.cpp
@@ -0,0 +1,62 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <boost/container/throw_exception.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+static bool bad_alloc_called = false;
+static bool out_of_range_called = false;
+static bool length_error_called = false;
+static bool logic_error_called = false;
+static bool runtime_error_called = false;
+
+//User defined throw implementations
+namespace boost {
+namespace container {
+
+ void throw_bad_alloc()
+ { bad_alloc_called = true; }
+
+ void throw_out_of_range(const char* str)
+ { (void)str; out_of_range_called = true; }
+
+ void throw_length_error(const char* str)
+ { (void)str; length_error_called = true; }
+
+ void throw_logic_error(const char* str)
+ { (void)str; logic_error_called = true; }
+
+ void throw_runtime_error(const char* str)
+ { (void)str; runtime_error_called = true; }
+
+}} //boost::container
+
+int main()
+{
+ //Check user-defined throw callbacks are called
+ throw_bad_alloc();
+ BOOST_TEST(bad_alloc_called == true);
+ throw_out_of_range("dummy");
+ BOOST_TEST(out_of_range_called == true);
+ throw_length_error("dummy");
+ BOOST_TEST(length_error_called == true);
+ throw_logic_error("dummy");
+ BOOST_TEST(logic_error_called == true);
+ throw_runtime_error("dummy");
+ BOOST_TEST(runtime_error_called == true);
+ return ::boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/src/boost/libs/container/test/tree_test.cpp b/src/boost/libs/container/test/tree_test.cpp
new file mode 100644
index 000000000..e07559677
--- /dev/null
+++ b/src/boost/libs/container/test/tree_test.cpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/tree.hpp>
+#include <boost/container/adaptive_pool.hpp>
+#include <boost/container/new_allocator.hpp>
+#include <boost/move/traits.hpp>
+
+#include <iostream>
+
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+using namespace boost::container;
+
+typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+namespace dtl {
+
+//Instantiate base class as previous instantiations don't instantiate inherited members
+template class tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator<pair_t>
+ , tree_assoc_defaults
+ >;
+
+template class tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::allocator<pair_t>
+ , tree_assoc_defaults
+ >;
+
+template class tree
+ < pair_t
+ , select1st<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , adaptive_pool<pair_t>
+ , tree_assoc_defaults
+ >;
+
+template class tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , test::simple_allocator<test::movable_and_copyable_int>
+ , tree_assoc_defaults
+ >;
+
+template class tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , std::allocator<test::movable_and_copyable_int>
+ , tree_assoc_defaults
+ >;
+
+template class tree
+ < test::movable_and_copyable_int
+ , identity<test::movable_and_copyable_int>
+ , std::less<test::movable_and_copyable_int>
+ , adaptive_pool<test::movable_and_copyable_int>
+ , tree_assoc_defaults
+ >;
+
+} //dtl {
+
+}} //boost::container
+
+int main ()
+{
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default
+ {
+ typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree;
+ typedef tree::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ typedef tree::key_compare key_compare;
+ if (boost::has_trivial_destructor_after_move<tree>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value &&
+ boost::has_trivial_destructor_after_move<key_compare>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree;
+ typedef tree::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ typedef tree::key_compare key_compare;
+ if (boost::has_trivial_destructor_after_move<tree>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value &&
+ boost::has_trivial_destructor_after_move<key_compare>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp b/src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp
new file mode 100644
index 000000000..298607a8b
--- /dev/null
+++ b/src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp
@@ -0,0 +1,19 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/unsynchronized_pool_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "pool_resource_test.hpp"
+
+int main()
+{
+ test_pool_resource<boost::container::pmr::unsynchronized_pool_resource>();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/uses_allocator_test.cpp b/src/boost/libs/container/test/uses_allocator_test.cpp
new file mode 100644
index 000000000..39807f09e
--- /dev/null
+++ b/src/boost/libs/container/test/uses_allocator_test.cpp
@@ -0,0 +1,84 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/uses_allocator_fwd.hpp>
+
+#include <boost/container/uses_allocator.hpp>
+#include "propagation_test_allocator.hpp"
+
+struct not_uses_allocator
+{};
+
+struct uses_allocator_and_not_convertible_to_int
+{
+ typedef uses_allocator_and_not_convertible_to_int allocator_type;
+};
+
+struct uses_allocator_and_convertible_to_int
+{
+ typedef char allocator_type;
+};
+
+struct uses_erased_type_allocator
+{
+ typedef boost::container::erased_type allocator_type;
+};
+
+
+int main()
+{
+ using namespace boost::container;
+ //Using dummy classes
+ BOOST_STATIC_ASSERT(( false == uses_allocator
+ < not_uses_allocator, int>::value ));
+
+ BOOST_STATIC_ASSERT(( false == uses_allocator
+ < uses_allocator_and_not_convertible_to_int, int>::value ));
+
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < uses_allocator_and_convertible_to_int, int>::value ));
+
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < uses_erased_type_allocator, int>::value ));
+
+ //Using an allocator-like class
+ BOOST_STATIC_ASSERT(( false == uses_allocator
+ < allocator_argument_tester<NotUsesAllocator, 0>
+ , propagation_test_allocator<float, 0>
+ >::value ));
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < allocator_argument_tester<ConstructiblePrefix, 0>
+ , propagation_test_allocator<float, 0>
+ >::value ));
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < allocator_argument_tester<ConstructibleSuffix, 0>
+ , propagation_test_allocator<float, 0>
+ >::value ));
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < allocator_argument_tester<ErasedTypeSuffix, 0>
+ , propagation_test_allocator<float, 0>
+ >::value ));
+ BOOST_STATIC_ASSERT(( true == uses_allocator
+ < allocator_argument_tester<ErasedTypePrefix, 0>
+ , propagation_test_allocator<float, 0>
+ >::value ));
+ BOOST_STATIC_ASSERT(( true == constructible_with_allocator_prefix
+ < allocator_argument_tester<ConstructiblePrefix, 0> >::value ));
+
+ BOOST_STATIC_ASSERT(( true == constructible_with_allocator_suffix
+ < allocator_argument_tester<ConstructibleSuffix, 0> >::value ));
+
+ BOOST_STATIC_ASSERT(( true == constructible_with_allocator_prefix
+ < allocator_argument_tester<ErasedTypePrefix, 0> >::value ));
+
+ BOOST_STATIC_ASSERT(( true == constructible_with_allocator_suffix
+ < allocator_argument_tester<ErasedTypeSuffix, 0> >::value ));
+ return 0;
+}
diff --git a/src/boost/libs/container/test/vector_options_test.cpp b/src/boost/libs/container/test/vector_options_test.cpp
new file mode 100644
index 000000000..9b414fb8d
--- /dev/null
+++ b/src/boost/libs/container/test/vector_options_test.cpp
@@ -0,0 +1,121 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/detail/next_capacity.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+template<class Unsigned, class VectorType>
+void test_stored_size_type_impl()
+{
+ VectorType v;
+ typedef typename VectorType::size_type size_type;
+ typedef typename VectorType::value_type value_type;
+ size_type const max = Unsigned(-1);
+ v.resize(5);
+ v.resize(max);
+ BOOST_TEST_THROWS(v.resize(max+1), std::exception);
+ BOOST_TEST_THROWS(v.push_back(value_type(1)), std::exception);
+ BOOST_TEST_THROWS(v.insert(v.begin(), value_type(1)), std::exception);
+ BOOST_TEST_THROWS(v.emplace(v.begin(), value_type(1)),std::exception);
+ BOOST_TEST_THROWS(v.reserve(max+1), std::exception);
+ BOOST_TEST_THROWS(VectorType v2(max+1), std::exception);
+}
+
+template<class Unsigned>
+void test_stored_size_type()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = vector_options_t< stored_size<Unsigned> >;
+ #else
+ typedef typename vector_options
+ < stored_size<Unsigned> >::type options_t;
+ #endif
+
+ //Test first with a typical allocator
+ {
+ typedef vector<unsigned char, new_allocator<unsigned char>, options_t> vector_t;
+ test_stored_size_type_impl<Unsigned, vector_t>();
+ }
+ //Test with a V2 allocator
+ {
+ typedef vector<unsigned char, allocator<unsigned char>, options_t> vector_t;
+ test_stored_size_type_impl<Unsigned, vector_t>();
+ }
+}
+
+void test_growth_factor_50()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = vector_options_t< growth_factor<growth_factor_50> >;
+ #else
+ typedef vector_options
+ < growth_factor<growth_factor_50> >::type options_t;
+ #endif
+
+ vector<int, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == old_capacity + old_capacity/2);
+}
+
+void test_growth_factor_60()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = vector_options_t< growth_factor<growth_factor_60> >;
+ #else
+ typedef vector_options
+ < growth_factor<growth_factor_60> >::type options_t;
+ #endif
+
+ vector<int, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == old_capacity + 3*old_capacity/5);
+}
+
+void test_growth_factor_100()
+{
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ using options_t = vector_options_t< growth_factor<growth_factor_100> >;
+ #else
+ typedef vector_options
+ < growth_factor<growth_factor_100> >::type options_t;
+ #endif
+
+ vector<int, new_allocator<int>, options_t> v;
+
+ v.resize(5);
+ v.resize(v.capacity());
+ std::size_t old_capacity = v.capacity();
+ v.push_back(0);
+ std::size_t new_capacity = v.capacity();
+ BOOST_TEST(new_capacity == 2*old_capacity);
+}
+
+int main()
+{
+ test_growth_factor_50();
+ test_growth_factor_60();
+ test_growth_factor_100();
+ test_stored_size_type<unsigned char>();
+ test_stored_size_type<unsigned short>();
+ return ::boost::report_errors();
+}
diff --git a/src/boost/libs/container/test/vector_test.cpp b/src/boost/libs/container/test/vector_test.cpp
new file mode 100644
index 000000000..c9b82cc38
--- /dev/null
+++ b/src/boost/libs/container/test/vector_test.cpp
@@ -0,0 +1,364 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// the tests trigger deprecation warnings when compiled with msvc in C++17 mode
+#if defined(_MSVC_LANG) && _MSVC_LANG > 201402
+// warning STL4009: std::allocator<void> is deprecated in C++17
+# define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING
+#endif
+
+#include <memory>
+#include <iostream>
+
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+int test_expand_bwd()
+{
+ //Now test all back insertion possibilities
+
+ //First raw ints
+ typedef test::expand_bwd_test_allocator<int>
+ int_allocator_type;
+ typedef vector<int, int_allocator_type>
+ int_vector;
+ if(!test::test_all_expand_bwd<int_vector>())
+ return 1;
+
+ //Now user defined copyable int
+ typedef test::expand_bwd_test_allocator<test::copyable_int>
+ copyable_int_allocator_type;
+ typedef vector<test::copyable_int, copyable_int_allocator_type>
+ copyable_int_vector;
+ if(!test::test_all_expand_bwd<copyable_int_vector>())
+ return 1;
+
+ return 0;
+}
+
+struct X;
+
+template<typename T>
+struct XRef
+{
+ explicit XRef(T* ptr) : ptr(ptr) {}
+ operator T*() const { return ptr; }
+ T* ptr;
+};
+
+struct X
+{
+ XRef<X const> operator&() const { return XRef<X const>(this); }
+ XRef<X> operator&() { return XRef<X>(this); }
+};
+
+
+bool test_smart_ref_type()
+{
+ boost::container::vector<X> x(5);
+ return x.empty();
+}
+
+class recursive_vector
+{
+ public:
+ recursive_vector & operator=(const recursive_vector &x)
+ { this->vector_ = x.vector_; return *this; }
+
+ int id_;
+ vector<recursive_vector> vector_;
+ vector<recursive_vector>::iterator it_;
+ vector<recursive_vector>::const_iterator cit_;
+ vector<recursive_vector>::reverse_iterator rit_;
+ vector<recursive_vector>::const_reverse_iterator crit_;
+};
+
+void recursive_vector_test()//Test for recursive types
+{
+ vector<recursive_vector> recursive_vector_vector;
+}
+
+enum Test
+{
+ zero, one, two, three, four, five, six
+};
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+ template<class ValueType>
+ struct apply
+ {
+ typedef vector< ValueType
+ , typename allocator_traits<VoidAllocator>
+ ::template portable_rebind_alloc<ValueType>::type
+ > type;
+ };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+ typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+ if(test::vector_test<MyCont>())
+ return 1;
+ if(test::vector_test<MyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyMoveCont>())
+ return 1;
+ if(test::vector_test<MyCopyCont>())
+ return 1;
+
+ return 0;
+}
+
+struct boost_container_vector;
+
+namespace boost { namespace container { namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_vector>
+{
+ template <class T, class Allocator>
+ struct apply
+ {
+ typedef boost::container::vector<T, Allocator> type;
+ };
+};
+
+}}} //namespace boost::container::test
+
+template<typename T>
+class check_dealloc_allocator : public std::allocator<T>
+{
+ public:
+ bool allocate_zero_called_;
+ bool deallocate_called_without_allocate_;
+
+ check_dealloc_allocator()
+ : std::allocator<T>()
+ , allocate_zero_called_(false)
+ , deallocate_called_without_allocate_(false)
+ {}
+
+ T* allocate(std::size_t n)
+ {
+ if (n == 0) {
+ allocate_zero_called_ = true;
+ }
+ return std::allocator<T>::allocate(n);
+ }
+
+ void deallocate(T* p, std::size_t n)
+ {
+ if (n == 0 && !allocate_zero_called_) {
+ deallocate_called_without_allocate_ = true;
+ }
+ return std::allocator<T>::deallocate(p, n);
+ }
+};
+
+bool test_merge_empty_free()
+{
+ vector<int> source;
+ source.emplace_back(1);
+
+ vector< int, check_dealloc_allocator<int> > empty;
+ empty.merge(source.begin(), source.end());
+
+ return empty.get_stored_allocator().deallocate_called_without_allocate_;
+}
+
+int main()
+{
+ {
+ const std::size_t positions_length = 10;
+ std::size_t positions[positions_length];
+ vector<int> vector_int;
+ vector<int> vector_int2(positions_length);
+ for(std::size_t i = 0; i != positions_length; ++i){
+ positions[i] = 0u;
+ }
+ for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){
+ vector_int2[i] = (int)i;
+ }
+
+ vector_int.insert(vector_int.begin(), 999);
+
+ vector_int.insert_ordered_at(positions_length, positions + positions_length, vector_int2.end());
+
+ for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){
+ std::cout << vector_int[i] << std::endl;
+ }
+ }
+ recursive_vector_test();
+ {
+ //Now test move semantics
+ vector<recursive_vector> original;
+ vector<recursive_vector> move_ctor(boost::move(original));
+ vector<recursive_vector> move_assign;
+ move_assign = boost::move(move_ctor);
+ move_assign.swap(original);
+ }
+
+ ////////////////////////////////////
+ // Testing allocator implementations
+ ////////////////////////////////////
+ // std:allocator
+ if(test_cont_variants< std::allocator<void> >()){
+ std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+ return 1;
+ }
+ // boost::container::allocator
+ if(test_cont_variants< allocator<void> >()){
+ std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
+ return 1;
+ }
+
+ {
+ typedef vector<Test, std::allocator<Test> > MyEnumCont;
+ MyEnumCont v;
+ Test t;
+ v.push_back(t);
+ v.push_back(::boost::move(t));
+ v.push_back(Test());
+ }
+
+ if (test_smart_ref_type())
+ return 1;
+
+ ////////////////////////////////////
+ // Backwards expansion test
+ ////////////////////////////////////
+ if(test_expand_bwd())
+ return 1;
+
+ ////////////////////////////////////
+ // Default init test
+ ////////////////////////////////////
+ if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){
+ std::cerr << "Default init test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Emplace testing
+ ////////////////////////////////////
+ const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+ if(!boost::container::test::test_emplace< vector<test::EmplaceInt>, Options>()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Allocator propagation testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Initializer lists testing
+ ////////////////////////////////////
+ if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for<
+ boost::container::vector<int>
+ >()) {
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // Iterator testing
+ ////////////////////////////////////
+ {
+ typedef boost::container::vector<int> cont_int;
+ cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+ boost::intrusive::test::test_iterator_random< cont_int >(a);
+ if(boost::report_errors() != 0) {
+ return 1;
+ }
+ }
+
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+ ////////////////////////////////////
+ // Constructor Template Auto Deduction testing
+ ////////////////////////////////////
+ {
+ auto gold = std::vector{ 1, 2, 3 };
+ auto test = boost::container::vector(gold.begin(), gold.end());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+ return 1;
+ }
+ }
+ {
+ auto gold = std::vector{ 1, 2, 3 };
+ auto test = boost::container::vector(gold.begin(), gold.end(), boost::container::new_allocator<int>());
+ if (test.size() != 3) {
+ return 1;
+ }
+ if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+ return 1;
+ }
+ }
+#endif
+
+ if (test_merge_empty_free()) {
+ std::cerr << "Merge into empty vector test failed" << std::endl;
+ return 1;
+ }
+
+ ////////////////////////////////////
+ // has_trivial_destructor_after_move testing
+ ////////////////////////////////////
+ // default allocator
+ {
+ typedef boost::container::vector<int> cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+ // std::allocator
+ {
+ typedef boost::container::vector<int, std::allocator<int> > cont;
+ typedef cont::allocator_type allocator_type;
+ typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
+ if (boost::has_trivial_destructor_after_move<cont>::value !=
+ boost::has_trivial_destructor_after_move<allocator_type>::value &&
+ boost::has_trivial_destructor_after_move<pointer>::value) {
+ std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/container/test/vector_test.hpp b/src/boost/libs/container/test/vector_test.hpp
new file mode 100644
index 000000000..016da1a71
--- /dev/null
+++ b/src/boost/libs/container/test/vector_test.hpp
@@ -0,0 +1,563 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
+#define BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <vector>
+#include <iostream>
+#include <list>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/static_assert.hpp>
+
+#include "print_container.hpp"
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "emplace_test.hpp"
+#include "input_from_forward_iterator.hpp"
+#include "insert_test.hpp"
+#include "container_common_tests.hpp"
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class Vector>
+struct vector_hash_function_capacity
+{
+ typedef typename Vector::size_type size_type;
+ template <typename U, size_type (U::*)() const> struct Check;
+ template <typename U> static char func(Check<U, &U::capacity> *);
+ template <typename U> static int func(...);
+
+ public:
+ static const bool value = sizeof(func<Vector>(0)) == sizeof(char);
+};
+
+template<class V1, class V2>
+bool vector_vector_hash_function_capacity_only(V1&, V2&, boost::container::dtl::false_type)
+{
+ return true;
+}
+
+template<class MyBoostVector, class MyStdVector>
+bool vector_vector_hash_function_capacity_only(MyBoostVector&boostvector, MyStdVector&stdvector, boost::container::dtl::true_type)
+{
+ //deque has no reserve
+ boostvector.reserve(boostvector.size()*2);
+ stdvector.reserve(stdvector.size()*2);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ std::size_t cap = boostvector.capacity();
+ boostvector.reserve(cap*2);
+ stdvector.reserve(cap*2);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+ boostvector.resize(0);
+ stdvector.resize(0);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ boostvector.resize(cap*2);
+ stdvector.resize(cap*2);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ boostvector.resize(cap*2);
+ stdvector.resize(cap*2);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ return true;
+}
+
+
+template<class V1, class V2>
+bool vector_copyable_only(V1&, V2&, boost::container::dtl::false_type)
+{
+ return true;
+}
+
+//Function to check if both sets are equal
+template<class MyBoostVector, class MyStdVector>
+bool vector_copyable_only(MyBoostVector &boostvector, MyStdVector &stdvector, boost::container::dtl::true_type)
+{
+ typedef typename MyBoostVector::value_type IntType;
+ std::size_t size = boostvector.size();
+ boostvector.insert(boostvector.end(), 50, IntType(1));
+ stdvector.insert(stdvector.end(), 50, 1);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ {
+ IntType move_me(1);
+ boostvector.insert(boostvector.begin()+size/2, 50, boost::move(move_me));
+ stdvector.insert(stdvector.begin()+size/2, 50, 1);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+ }
+ {
+ IntType move_me(2);
+ boostvector.assign(boostvector.size()/2, boost::move(move_me));
+ stdvector.assign(stdvector.size()/2, 2);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+ }
+ {
+ IntType move_me(3);
+ boostvector.assign(boostvector.size()*3-1, boost::move(move_me));
+ stdvector.assign(stdvector.size()*3-1, 3);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+ }
+
+ {
+ IntType copy_me(3);
+ const IntType ccopy_me(3);
+ boostvector.push_back(copy_me);
+ stdvector.push_back(int(3));
+ boostvector.push_back(ccopy_me);
+ stdvector.push_back(int(3));
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+ }
+ { //Vector(const Vector &)
+ ::boost::movelib::unique_ptr<MyBoostVector> const pv1 =
+ ::boost::movelib::make_unique<MyBoostVector>(boostvector);
+ ::boost::movelib::unique_ptr<MyStdVector> const pv2 =
+ ::boost::movelib::make_unique<MyStdVector>(stdvector);
+
+ MyBoostVector &v1 = *pv1;
+ MyStdVector &v2 = *pv2;
+
+ boostvector.clear();
+ stdvector.clear();
+ boostvector.assign(v1.begin(), v1.end());
+ stdvector.assign(v2.begin(), v2.end());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+ { //Vector(const Vector &, alloc)
+ ::boost::movelib::unique_ptr<MyBoostVector> const pv1 =
+ ::boost::movelib::make_unique<MyBoostVector>(boostvector, typename MyBoostVector::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdVector> const pv2 =
+ ::boost::movelib::make_unique<MyStdVector>(stdvector);
+
+ MyBoostVector &v1 = *pv1;
+ MyStdVector &v2 = *pv2;
+
+ boostvector.clear();
+ stdvector.clear();
+ boostvector.assign(v1.begin(), v1.end());
+ stdvector.assign(v2.begin(), v2.end());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+ { //Vector(n, T)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100, int(5));
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100, IntType(5));
+ if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+ }
+ { //Vector(n, T, alloc)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100, int(5));
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100, IntType(5), typename MyBoostVector::allocator_type());
+ if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+ }
+ { //Vector(It, It)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+ ::boost::movelib::make_unique<MyBoostVector>(boostvectorp->begin(), boostvectorp->end());
+ if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+ }
+ { //Vector(It, It, alloc)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+ ::boost::movelib::make_unique<MyBoostVector>(boostvectorp->begin(), boostvectorp->end(), typename MyBoostVector::allocator_type());
+ if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+ }
+ { //resize(n, T)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>();
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>();
+ stdvectorp->resize(100, int(9));
+ boostvectorp->resize(100, IntType(9));
+ if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+ }
+ //operator=
+ {
+ //Copy constructor test
+ MyBoostVector bcopy((const MyBoostVector&) boostvector);
+ MyStdVector scopy((const MyStdVector&) stdvector);
+ MyBoostVector bcopy2(boostvector);
+ MyStdVector scopy2(stdvector);
+
+ if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+ if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+
+ //Assignment from a smaller vector
+ bcopy2.erase(bcopy2.begin() + bcopy2.size()/2, bcopy2.end());
+ scopy2.erase(scopy2.begin() + scopy2.size()/2, scopy2.end());
+ bcopy = bcopy2;
+ scopy = scopy2;
+ if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+
+ //Assignment from a bigger vector with capacity
+ bcopy2 = boostvector;
+ scopy2 = stdvector;
+ if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+
+ //Assignment from bigger vector with no capacity
+ bcopy2.erase(bcopy2.begin() + bcopy2.size()/2, bcopy2.end());
+ scopy2.erase(scopy2.begin() + scopy2.size()/2, scopy2.end());
+ bcopy2.shrink_to_fit();
+ MyStdVector(scopy2).swap(scopy2);
+
+ bcopy2 = boostvector;
+ scopy2 = stdvector;
+ if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+
+ //Assignment with equal capacity
+ bcopy2 = boostvector;
+ scopy2 = stdvector;
+ if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+ }
+
+ return true;
+}
+
+template<class MyBoostVector>
+int vector_test()
+{
+ typedef std::vector<int> MyStdVector;
+ typedef typename MyBoostVector::value_type IntType;
+ const int max = 100;
+
+ if(!test_range_insertion<MyBoostVector>()){
+ return 1;
+ }
+ { //Vector(n)
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+ }
+ { //Vector(n, alloc)
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100, typename MyBoostVector::allocator_type());
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+ }
+ { //Vector(Vector &&)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+ ::boost::movelib::make_unique<MyBoostVector>(::boost::move(*boostvectorp));
+ if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+ }
+ { //Vector(Vector &&, alloc)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+ ::boost::movelib::make_unique<MyBoostVector>
+ (::boost::move(*boostvectorp), typename MyBoostVector::allocator_type());
+ if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+ }
+ { //Vector operator=(Vector &&)
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+ ::boost::movelib::make_unique<MyStdVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+ ::boost::movelib::make_unique<MyBoostVector>(100);
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+ ::boost::movelib::make_unique<MyBoostVector>();
+ *boostvectorp2 = ::boost::move(*boostvectorp);
+ if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+ }
+ {
+ ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp = ::boost::movelib::make_unique<MyBoostVector>();
+ ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp = ::boost::movelib::make_unique<MyStdVector>();
+
+ MyBoostVector & boostvector = *boostvectorp;
+ MyStdVector & stdvector = *stdvectorp;
+
+ boostvector.resize(100);
+ stdvector.resize(100);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ boostvector.resize(200);
+ stdvector.resize(200);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ boostvector.resize(0);
+ stdvector.resize(0);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ for(int i = 0; i < max; ++i){
+ IntType new_int(i);
+ boostvector.insert(boostvector.end(), boost::move(new_int));
+ stdvector.insert(stdvector.end(), i);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ typename MyBoostVector::iterator boostit(boostvector.begin());
+ typename MyStdVector::iterator stdit(stdvector.begin());
+ typename MyBoostVector::const_iterator cboostit = boostit;
+ (void)cboostit;
+ ++boostit; ++stdit;
+ boostvector.erase(boostit);
+ stdvector.erase(stdit);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ boostvector.erase(boostvector.begin());
+ stdvector.erase(stdvector.begin());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ {
+ //Initialize values
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType new_int(-1);
+ BOOST_STATIC_ASSERT((boost::container::test::is_copyable<boost::container::test::movable_int>::value == false));
+ aux_vect[i] = boost::move(new_int);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -1;
+ }
+ typename MyBoostVector::iterator insert_it =
+ boostvector.insert(boostvector.end()
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(aux_vect + 50));
+ if(std::size_t(boost::container::iterator_distance(insert_it, boostvector.end())) != 50) return 1;
+ stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ for(int i = 0, j = static_cast<int>(boostvector.size()); i < j; ++i){
+ boostvector.erase(boostvector.begin());
+ stdvector.erase(stdvector.begin());
+ }
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+ {
+ boostvector.resize(100);
+ stdvector.resize(100);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ IntType aux_vect[50];
+ for(int i = 0; i < 50; ++i){
+ IntType new_int(-i);
+ aux_vect[i] = boost::move(new_int);
+ }
+ int aux_vect2[50];
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -i;
+ }
+ typename MyBoostVector::size_type old_size = boostvector.size();
+ typename MyBoostVector::iterator insert_it =
+ boostvector.insert(boostvector.begin() + old_size/2
+ ,boost::make_move_iterator(&aux_vect[0])
+ ,boost::make_move_iterator(aux_vect + 50));
+ if(boostvector.begin() + old_size/2 != insert_it) return 1;
+ stdvector.insert(stdvector.begin() + old_size/2, aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ for(int i = 0; i < 50; ++i){
+ IntType new_int(-i);
+ aux_vect[i] = boost::move(new_int);
+ }
+
+ for(int i = 0; i < 50; ++i){
+ aux_vect2[i] = -i;
+ }
+ old_size = boostvector.size();
+ //Now try with input iterators instead
+ insert_it = boostvector.insert(boostvector.begin() + old_size/2
+ ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+ ,boost::make_move_iterator(make_input_from_forward_iterator(aux_vect + 50))
+ );
+ if(boostvector.begin() + old_size/2 != insert_it) return 1;
+ stdvector.insert(stdvector.begin() + old_size/2, aux_vect2, aux_vect2 + 50);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+
+ boostvector.shrink_to_fit();
+ MyStdVector(stdvector).swap(stdvector);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ boostvector.shrink_to_fit();
+ MyStdVector(stdvector).swap(stdvector);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ { //push_back with not enough capacity
+ IntType push_back_this(1);
+ boostvector.push_back(boost::move(push_back_this));
+ stdvector.push_back(int(1));
+ boostvector.push_back(IntType(1));
+ stdvector.push_back(int(1));
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+
+ { //test back()
+ const IntType test_this(1);
+ if(test_this != boostvector.back()) return 1;
+ }
+ { //pop_back with enough capacity
+ boostvector.pop_back();
+ boostvector.pop_back();
+ stdvector.pop_back();
+ stdvector.pop_back();
+
+ IntType push_back_this(1);
+ boostvector.push_back(boost::move(push_back_this));
+ stdvector.push_back(int(1));
+ boostvector.push_back(IntType(1));
+ stdvector.push_back(int(1));
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+
+ if(!vector_copyable_only(boostvector, stdvector
+ ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+ return 1;
+ }
+
+ boostvector.erase(boostvector.begin());
+ stdvector.erase(stdvector.begin());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ for(int i = 0; i < max; ++i){
+ IntType insert_this(i);
+ boostvector.insert(boostvector.begin(), boost::move(insert_this));
+ stdvector.insert(stdvector.begin(), i);
+ boostvector.insert(boostvector.begin(), IntType(i));
+ stdvector.insert(stdvector.begin(), int(i));
+ }
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ //some comparison operators
+ if(!(boostvector == boostvector))
+ return 1;
+ if(boostvector != boostvector)
+ return 1;
+ if(boostvector < boostvector)
+ return 1;
+ if(boostvector > boostvector)
+ return 1;
+ if(!(boostvector <= boostvector))
+ return 1;
+ if(!(boostvector >= boostvector))
+ return 1;
+
+ //Test insertion from list
+ {
+ std::list<int> l(50, int(1));
+ typename MyBoostVector::iterator it_insert =
+ boostvector.insert(boostvector.begin(), l.begin(), l.end());
+ if(boostvector.begin() != it_insert) return 1;
+ stdvector.insert(stdvector.begin(), l.begin(), l.end());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ boostvector.assign(l.begin(), l.end());
+ stdvector.assign(l.begin(), l.end());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+ boostvector.clear();
+ stdvector.clear();
+ boostvector.assign(make_input_from_forward_iterator(l.begin()), make_input_from_forward_iterator(l.end()));
+ stdvector.assign(l.begin(), l.end());
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+
+ if(!vector_vector_hash_function_capacity_only(boostvector, stdvector, dtl::bool_<vector_hash_function_capacity<MyBoostVector>::value>()))
+ return 1;
+
+ boostvector.clear();
+ stdvector.clear();
+ boostvector.shrink_to_fit();
+ MyStdVector(stdvector).swap(stdvector);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+ boostvector.resize(100);
+ if(!test_nth_index_of(boostvector))
+ return 1;
+
+ }
+ std::cout << std::endl << "Test OK!" << std::endl;
+ return 0;
+}
+
+template<typename VectorContainerType>
+bool test_vector_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ typedef typename VectorContainerType::allocator_type allocator_type;
+ {
+ const VectorContainerType testedVector = {1, 2, 3};
+ const std::vector<int> expectedVector = {1, 2, 3};
+ if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+ }
+ {
+ const VectorContainerType testedVector( { 1, 2, 3 }, allocator_type() );
+ const std::vector<int> expectedVector = {1, 2, 3};
+ if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+ }
+ {
+ VectorContainerType testedVector = {1, 2, 3};
+ testedVector = {11, 12, 13};
+
+ const std::vector<int> expectedVector = {11, 12, 13};
+ if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+ }
+
+ {
+ VectorContainerType testedVector = {1, 2, 3};
+ testedVector.assign({5, 6, 7});
+
+ const std::vector<int> expectedVector = {5, 6, 7};
+ if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+ }
+
+ {
+ VectorContainerType testedVector = {1, 2, 3};
+ testedVector.insert(testedVector.cend(), {5, 6, 7});
+
+ const std::vector<int> expectedVector = {1, 2, 3, 5, 6, 7};
+ if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+ }
+ return true;
+#else
+ return true;
+#endif
+}
+
+} //namespace test{
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER