forked from boostorg/container
- Modified relational operators to be friend inline definitions. This allows compilation checking when instantiating classes, avoids predeclarations and results in less verbose code.
- First to make associative containers' tree implementation configurable.
This commit is contained in:
@@ -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/alloc_lib_auto_link.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;
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
void *ptr = boost_cont_alloc(50, 98, &received);
|
||||
if(boost_cont_size(ptr) != received)
|
||||
return false;
|
||||
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
|
||||
return false;
|
||||
|
||||
if(boost_cont_all_deallocated())
|
||||
return false;
|
||||
|
||||
boost_cont_grow(ptr, received + 20, received + 30, &received);
|
||||
|
||||
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
|
||||
return false;
|
||||
|
||||
if(boost_cont_size(ptr) != received)
|
||||
return false;
|
||||
|
||||
if(!boost_cont_shrink(ptr, 100, 140, &received, 1))
|
||||
return false;
|
||||
|
||||
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
|
||||
return false;
|
||||
|
||||
if(!boost_cont_shrink(ptr, 0, 140, &received, 1))
|
||||
return false;
|
||||
|
||||
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
|
||||
return false;
|
||||
|
||||
if(boost_cont_shrink(ptr, 0, received/2, &received, 1))
|
||||
return false;
|
||||
|
||||
if(boost_cont_allocated_memory() != boost_cont_chunksize(ptr))
|
||||
return false;
|
||||
|
||||
if(boost_cont_size(ptr) != received)
|
||||
return false;
|
||||
|
||||
boost_cont_free(ptr);
|
||||
|
||||
boost_cont_malloc_check();
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vector_test()
|
||||
{
|
||||
typedef boost::container::vector<int, allocator<int> > Vector;
|
||||
if(!boost_cont_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(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool list_test()
|
||||
{
|
||||
typedef boost::container::list<int, allocator<int> > List;
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
{
|
||||
const int NumElem = 1000;
|
||||
List l;
|
||||
int values[NumElem];
|
||||
l.insert(l.end(), &values[0], &values[NumElem]);
|
||||
}
|
||||
if(!boost_cont_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;
|
||||
}
|
||||
@@ -0,0 +1,851 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <new>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <algorithm> //std::remove
|
||||
#include <boost/container/detail/alloc_lib_auto_link.hpp>
|
||||
|
||||
namespace boost { namespace container { namespace test {
|
||||
|
||||
static const int NumIt = 2000;
|
||||
|
||||
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(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
boost_cont_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 = boost_cont_malloc(i);
|
||||
if(!ptr)
|
||||
break;
|
||||
buffers.push_back(ptr);
|
||||
}
|
||||
|
||||
switch(t){
|
||||
case DirectDeallocation:
|
||||
{
|
||||
for(int j = 0, max = (int)buffers.size()
|
||||
;j < max
|
||||
;++j){
|
||||
boost_cont_free(buffers[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InverseDeallocation:
|
||||
{
|
||||
for(int j = (int)buffers.size()
|
||||
;j--
|
||||
;){
|
||||
boost_cont_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;
|
||||
boost_cont_free(buffers[pos]);
|
||||
buffers.erase(buffers.begin()+pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
//bool ok = free_memory == a.get_free_memory() &&
|
||||
//a.all_memory_deallocated() && a.check_sanity();
|
||||
//if(!ok) return ok;
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_malloc_check();
|
||||
std::vector<void*> buffers;
|
||||
|
||||
//Allocate buffers with extra memory
|
||||
for(int i = 0; i != NumIt; ++i){
|
||||
void *ptr = boost_cont_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;
|
||||
void* try_result = boost_cont_allocation_command
|
||||
( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 1, i*2
|
||||
, i, &try_received_size, (char*)buffers[i]).first;
|
||||
|
||||
std::size_t received_size;
|
||||
void* result = boost_cont_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;
|
||||
boost_cont_free(buffers[pos]);
|
||||
buffers.erase(buffers.begin()+pos);
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_malloc_check();
|
||||
std::vector<void*> buffers;
|
||||
|
||||
//Allocate buffers with extra memory
|
||||
for(int i = 0; i != NumIt; ++i){
|
||||
void *ptr = boost_cont_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;
|
||||
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(boost_cont_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;
|
||||
boost_cont_free(buffers[pos]);
|
||||
buffers.erase(buffers.begin()+pos);
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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;
|
||||
void *ptr = boost_cont_allocation_command
|
||||
(BOOST_CONTAINER_ALLOCATE_NEW, 1, i, i*2, &received_size, 0).first;
|
||||
if(!ptr){
|
||||
ptr = boost_cont_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;
|
||||
bool size_reduced_flag;
|
||||
if(true == (size_reduced_flag = !!
|
||||
boost_cont_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;
|
||||
std::size_t request_size = received_sizes[i];
|
||||
if(boost_cont_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;
|
||||
boost_cont_free(buffers[pos]);
|
||||
buffers.erase(buffers.begin()+pos);
|
||||
}
|
||||
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_malloc_check();
|
||||
std::vector<void*> buffers;
|
||||
|
||||
//Allocate buffers with extra memory
|
||||
for(int i = 0; i != NumIt; ++i){
|
||||
void *ptr = boost_cont_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){
|
||||
boost_cont_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;
|
||||
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(boost_cont_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;
|
||||
boost_cont_free(buffers[pos]);
|
||||
buffers.erase(buffers.begin()+pos);
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_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 = boost_cont_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){
|
||||
boost_cont_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;
|
||||
boost_cont_command_ret_t ret = boost_cont_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
|
||||
boost_cont_free(ptr);
|
||||
boost_cont_malloc_check();
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//This test allocates memory with different alignments
|
||||
//and checks returned memory is aligned.
|
||||
|
||||
bool test_aligned_allocation()
|
||||
{
|
||||
boost_cont_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 = boost_cont_memalign(i-1, j);
|
||||
if(!ptr){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(((std::size_t)ptr & (j - 1)) != 0)
|
||||
return false;
|
||||
boost_cont_free(ptr);
|
||||
//if(!a.all_memory_deallocated() || !a.check_sanity()){
|
||||
// return false;
|
||||
//}
|
||||
}
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_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 = boost_cont_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--;){
|
||||
boost_cont_free(buffers[k]);
|
||||
}
|
||||
buffers.clear();
|
||||
//if(!a.all_memory_deallocated() && a.check_sanity())
|
||||
// return false;
|
||||
if(!continue_loop)
|
||||
break;
|
||||
}
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_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 = boost_cont_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){
|
||||
boost_cont_free(buffers2[i]);
|
||||
buffers2[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//if(!a.check_sanity())
|
||||
//return false;
|
||||
|
||||
std::vector<void*> buffers;
|
||||
for(int i = 0; i != NumIt/10; ++i){
|
||||
boost_cont_memchain chain;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
|
||||
boost_cont_multialloc_nodes((i+1)*2, i+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
|
||||
boost_cont_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){
|
||||
boost_cont_free(buffers[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InverseDeallocation:
|
||||
{
|
||||
for(int j = (int)buffers.size()
|
||||
;j--
|
||||
;){
|
||||
boost_cont_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;
|
||||
boost_cont_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;
|
||||
boost_cont_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;
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_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()
|
||||
{
|
||||
boost_cont_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 = boost_cont_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){
|
||||
boost_cont_free(buffers2[i]);
|
||||
buffers2[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<void*> buffers;
|
||||
for(int i = 0; i != NumIt; ++i){
|
||||
boost_cont_memchain chain;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
|
||||
boost_cont_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
|
||||
boost_cont_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){
|
||||
boost_cont_free(buffers[j]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InverseDeallocation:
|
||||
{
|
||||
for(int j = (int)buffers.size()
|
||||
;j--
|
||||
;){
|
||||
boost_cont_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;
|
||||
boost_cont_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;
|
||||
boost_cont_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;
|
||||
}
|
||||
boost_cont_malloc_check();
|
||||
return 0 != boost_cont_all_deallocated();
|
||||
}
|
||||
|
||||
bool test_many_deallocation()
|
||||
{
|
||||
const std::size_t ArraySize = 11;
|
||||
std::vector<boost_cont_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){
|
||||
boost_cont_memchain chain;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
|
||||
boost_cont_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
|
||||
boost_cont_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){
|
||||
boost_cont_multidealloc(&buffers[i]);
|
||||
}
|
||||
buffers.clear();
|
||||
|
||||
boost_cont_malloc_check();
|
||||
if(!boost_cont_all_deallocated())
|
||||
return false;
|
||||
|
||||
for(int i = 0; i != NumIt; ++i){
|
||||
boost_cont_memchain chain;
|
||||
BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
|
||||
boost_cont_multialloc_nodes(ArraySize, i*4+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
|
||||
boost_cont_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){
|
||||
boost_cont_multidealloc(&buffers[i]);
|
||||
}
|
||||
buffers.clear();
|
||||
|
||||
boost_cont_malloc_check();
|
||||
if(!boost_cont_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 != boost_cont_all_deallocated();
|
||||
}
|
||||
|
||||
}}} //namespace boost { namespace container { namespace test {
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
if(!boost::container::test::test_all_allocation())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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 <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include "print_container.hpp"
|
||||
#include "check_equal_containers.hpp"
|
||||
#include "movable_int.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "emplace_test.hpp"
|
||||
#include "input_from_forward_iterator.hpp"
|
||||
#include <boost/move/utility.hpp>
|
||||
#include <boost/move/iterator.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include "insert_test.hpp"
|
||||
|
||||
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(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
|
||||
@@ -0,0 +1,439 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/flat_map.hpp>
|
||||
#include <boost/container/allocator.hpp>
|
||||
#include <boost/container/node_allocator.hpp>
|
||||
#include <boost/container/adaptive_pool.hpp>
|
||||
|
||||
#include "print_container.hpp"
|
||||
#include "dummy_test_allocator.hpp"
|
||||
#include "movable_int.hpp"
|
||||
#include "map_test.hpp"
|
||||
#include "propagate_allocator_test.hpp"
|
||||
#include "emplace_test.hpp"
|
||||
#include <vector>
|
||||
#include <boost/container/detail/flat_tree.hpp>
|
||||
|
||||
using namespace boost::container;
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//Explicit instantiation to detect compilation errors
|
||||
|
||||
//flat_map
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::dummy_test_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
//flat_multimap
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::dummy_test_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class flat_multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator
|
||||
< std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
//As flat container iterators are typedefs for vector::[const_]iterator,
|
||||
//no need to explicit instantiate them
|
||||
|
||||
}} //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_;
|
||||
|
||||
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_map<recursive_flat_multimap, recursive_flat_multimap> map_;
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
class flat_tree_propagate_test_wrapper
|
||||
: public container_detail::flat_tree<T, T, container_detail::identity<T>, std::less<T>, A>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(flat_tree_propagate_test_wrapper)
|
||||
typedef container_detail::flat_tree<T, T, container_detail::identity<T>, std::less<T>, A> Base;
|
||||
public:
|
||||
flat_tree_propagate_test_wrapper()
|
||||
: Base()
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper(const flat_tree_propagate_test_wrapper &x)
|
||||
: Base(x)
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
|
||||
: Base(boost::move(static_cast<Base&>(x)))
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(flat_tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(x); return *this; }
|
||||
|
||||
flat_tree_propagate_test_wrapper &operator=(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
|
||||
|
||||
void swap(flat_tree_propagate_test_wrapper &x)
|
||||
{ this->Base::swap(x); }
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
template<class VoidAllocator>
|
||||
struct GetAllocatorMap
|
||||
{
|
||||
template<class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef flat_map< ValueType
|
||||
, ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type
|
||||
> map_type;
|
||||
|
||||
typedef flat_multimap< ValueType
|
||||
, ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc< std::pair<ValueType, ValueType> >::type
|
||||
> multimap_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class VoidAllocator>
|
||||
int test_map_variants()
|
||||
{
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::map_type MyMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::map_type MyMoveMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::map_type MyCopyMap;
|
||||
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::multimap_type MyMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
|
||||
|
||||
typedef std::map<int, int> MyStdMap;
|
||||
typedef std::multimap<int, int> MyStdMultiMap;
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyMap
|
||||
,MyStdMap
|
||||
,MyMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyMoveMap
|
||||
,MyStdMap
|
||||
,MyMoveMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyCopyMoveMap
|
||||
,MyStdMap
|
||||
,MyCopyMoveMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyCopyMap
|
||||
,MyStdMap
|
||||
,MyCopyMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::container::test;
|
||||
|
||||
//Allocator argument container
|
||||
{
|
||||
flat_map<int, int> map_((std::allocator<std::pair<int, int> >()));
|
||||
flat_multimap<int, int> multimap_((std::allocator<std::pair<int, int> >()));
|
||||
}
|
||||
//Now test move semantics
|
||||
{
|
||||
test_move<flat_map<recursive_flat_map, recursive_flat_map> >();
|
||||
test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >();
|
||||
}
|
||||
|
||||
if(!flat_tree_ordered_insertion_test()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< std::allocator<void> >()){
|
||||
std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< allocator<void> >()){
|
||||
std::cerr << "test_map_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< node_allocator<void> >()){
|
||||
std::cerr << "test_map_variants< node_allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< adaptive_pool<void> >()){
|
||||
std::cerr << "test_map_variants< adaptive_pool<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!boost::container::test::test_propagate_allocator<flat_tree_propagate_test_wrapper>())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/flat_set.hpp>
|
||||
#include <boost/container/allocator.hpp>
|
||||
#include <boost/container/node_allocator.hpp>
|
||||
#include <boost/container/adaptive_pool.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 <vector>
|
||||
#include <boost/container/detail/flat_tree.hpp>
|
||||
|
||||
using namespace boost::container;
|
||||
|
||||
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>
|
||||
, test::dummy_test_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
//flat_multiset
|
||||
template class flat_multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::dummy_test_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<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>
|
||||
, std::allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class flat_multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
//As flat container iterators are typedefs for vector::[const_]iterator,
|
||||
//no need to explicit instantiate them
|
||||
|
||||
}} //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_;
|
||||
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_;
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
class flat_tree_propagate_test_wrapper
|
||||
: public container_detail::flat_tree<T, T, container_detail::identity<T>, std::less<T>, A>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(flat_tree_propagate_test_wrapper)
|
||||
typedef container_detail::flat_tree<T, T, container_detail::identity<T>, std::less<T>, A> Base;
|
||||
public:
|
||||
flat_tree_propagate_test_wrapper()
|
||||
: Base()
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper(const flat_tree_propagate_test_wrapper &x)
|
||||
: Base(x)
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
|
||||
: Base(boost::move(static_cast<Base&>(x)))
|
||||
{}
|
||||
|
||||
flat_tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(flat_tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(x); return *this; }
|
||||
|
||||
flat_tree_propagate_test_wrapper &operator=(BOOST_RV_REF(flat_tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
|
||||
|
||||
void swap(flat_tree_propagate_test_wrapper &x)
|
||||
{ this->Base::swap(x); }
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//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_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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
template<class VoidAllocator>
|
||||
struct GetAllocatorSet
|
||||
{
|
||||
template<class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef flat_set < ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type
|
||||
> set_type;
|
||||
|
||||
typedef flat_multiset < ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type
|
||||
> multiset_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class VoidAllocator>
|
||||
int test_set_variants()
|
||||
{
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::set_type MySet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
|
||||
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
|
||||
|
||||
typedef std::set<int> MyStdSet;
|
||||
typedef std::multiset<int> MyStdMultiSet;
|
||||
|
||||
if (0 != test::set_test<
|
||||
MySet
|
||||
,MyStdSet
|
||||
,MyMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyMoveSet
|
||||
,MyStdSet
|
||||
,MyMoveMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyCopyMoveSet
|
||||
,MyStdSet
|
||||
,MyCopyMoveMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyCopySet
|
||||
,MyStdSet
|
||||
,MyCopyMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::container::test;
|
||||
|
||||
//Allocator argument container
|
||||
{
|
||||
flat_set<int> set_((std::allocator<int>()));
|
||||
flat_multiset<int> multiset_((std::allocator<int>()));
|
||||
}
|
||||
//Now test move semantics
|
||||
{
|
||||
test_move<flat_set<recursive_flat_set> >();
|
||||
test_move<flat_multiset<recursive_flat_multiset> >();
|
||||
}
|
||||
|
||||
if(!flat_tree_ordered_insertion_test()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< std::allocator<void> >()){
|
||||
std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< allocator<void> >()){
|
||||
std::cerr << "test_set_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< node_allocator<void> >()){
|
||||
std::cerr << "test_set_variants< node_allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< adaptive_pool<void> >()){
|
||||
std::cerr << "test_set_variants< adaptive_pool<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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_propagate_allocator<flat_tree_propagate_test_wrapper>())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/allocator.hpp>
|
||||
#include <boost/container/node_allocator.hpp>
|
||||
#include <boost/container/adaptive_pool.hpp>
|
||||
|
||||
#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"
|
||||
|
||||
using namespace boost::container;
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
//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::dummy_test_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
|
||||
template class map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class map
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
//multimap
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::dummy_test_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
template class multimap
|
||||
< test::movable_and_copyable_int
|
||||
, test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator
|
||||
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
|
||||
>;
|
||||
|
||||
}} //boost::container
|
||||
|
||||
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_;
|
||||
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_;
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
class tree_propagate_test_wrapper
|
||||
: public container_detail::tree<T, T, container_detail::identity<T>, std::less<T>, A, red_black_tree>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(tree_propagate_test_wrapper)
|
||||
typedef container_detail::tree<T, T, container_detail::identity<T>, std::less<T>, A, red_black_tree> Base;
|
||||
public:
|
||||
tree_propagate_test_wrapper()
|
||||
: Base()
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper(const tree_propagate_test_wrapper &x)
|
||||
: Base(x)
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper(BOOST_RV_REF(tree_propagate_test_wrapper) x)
|
||||
: Base(boost::move(static_cast<Base&>(x)))
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(x); return *this; }
|
||||
|
||||
tree_propagate_test_wrapper &operator=(BOOST_RV_REF(tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
|
||||
|
||||
void swap(tree_propagate_test_wrapper &x)
|
||||
{ this->Base::swap(x); }
|
||||
};
|
||||
|
||||
|
||||
template<class VoidAllocator>
|
||||
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
|
||||
> map_type;
|
||||
|
||||
typedef multimap< ValueType
|
||||
, ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
|
||||
> multimap_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class VoidAllocator>
|
||||
int test_map_variants()
|
||||
{
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::map_type MyMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::map_type MyMoveMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::map_type MyCopyMap;
|
||||
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<int>::multimap_type MyMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
|
||||
typedef typename GetAllocatorMap<VoidAllocator>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
|
||||
|
||||
typedef std::map<int, int> MyStdMap;
|
||||
typedef std::multimap<int, int> MyStdMultiMap;
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyMap
|
||||
,MyStdMap
|
||||
,MyMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyMoveMap
|
||||
,MyStdMap
|
||||
,MyMoveMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyCopyMoveMap
|
||||
,MyStdMap
|
||||
,MyCopyMoveMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::map_test<
|
||||
MyCopyMap
|
||||
,MyStdMap
|
||||
,MyCopyMultiMap
|
||||
,MyStdMultiMap>()){
|
||||
std::cout << "Error in map_test<MyBoostMap>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
//Recursive container instantiation
|
||||
{
|
||||
map<recursive_map, recursive_map> map_;
|
||||
multimap<recursive_multimap, recursive_multimap> multimap_;
|
||||
}
|
||||
//Allocator argument container
|
||||
{
|
||||
map<int, int> map_((std::allocator<std::pair<const int, int> >()));
|
||||
multimap<int, int> multimap_((std::allocator<std::pair<const int, int> >()));
|
||||
}
|
||||
//Now test move semantics
|
||||
{
|
||||
test_move<map<recursive_map, recursive_map> >();
|
||||
test_move<multimap<recursive_multimap, recursive_multimap> >();
|
||||
}
|
||||
|
||||
if(test_map_variants< std::allocator<void> >()){
|
||||
std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< allocator<void> >()){
|
||||
std::cerr << "test_map_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< node_allocator<void> >()){
|
||||
std::cerr << "test_map_variants< node_allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_map_variants< adaptive_pool<void> >()){
|
||||
std::cerr << "test_map_variants< adaptive_pool<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!boost::container::test::test_propagate_allocator<tree_propagate_test_wrapper>())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
@@ -0,0 +1,300 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (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/allocator.hpp>
|
||||
#include <boost/container/node_allocator.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"
|
||||
|
||||
using namespace boost::container;
|
||||
|
||||
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::dummy_test_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class set
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
//multiset
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::dummy_test_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, test::simple_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, std::allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, adaptive_pool<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
template class multiset
|
||||
< test::movable_and_copyable_int
|
||||
, std::less<test::movable_and_copyable_int>
|
||||
, node_allocator<test::movable_and_copyable_int>
|
||||
>;
|
||||
|
||||
}} //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_;
|
||||
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_;
|
||||
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);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
class tree_propagate_test_wrapper
|
||||
: public container_detail::tree<T, T, container_detail::identity<T>, std::less<T>, A, red_black_tree>
|
||||
{
|
||||
BOOST_COPYABLE_AND_MOVABLE(tree_propagate_test_wrapper)
|
||||
typedef container_detail::tree<T, T, container_detail::identity<T>, std::less<T>, A, red_black_tree> Base;
|
||||
public:
|
||||
tree_propagate_test_wrapper()
|
||||
: Base()
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper(const tree_propagate_test_wrapper &x)
|
||||
: Base(x)
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper(BOOST_RV_REF(tree_propagate_test_wrapper) x)
|
||||
: Base(boost::move(static_cast<Base&>(x)))
|
||||
{}
|
||||
|
||||
tree_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(x); return *this; }
|
||||
|
||||
tree_propagate_test_wrapper &operator=(BOOST_RV_REF(tree_propagate_test_wrapper) x)
|
||||
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
|
||||
|
||||
void swap(tree_propagate_test_wrapper &x)
|
||||
{ this->Base::swap(x); }
|
||||
};
|
||||
|
||||
template<class VoidAllocator>
|
||||
struct GetAllocatorSet
|
||||
{
|
||||
template<class ValueType>
|
||||
struct apply
|
||||
{
|
||||
typedef set < ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type
|
||||
> set_type;
|
||||
|
||||
typedef multiset < ValueType
|
||||
, std::less<ValueType>
|
||||
, typename allocator_traits<VoidAllocator>
|
||||
::template portable_rebind_alloc<ValueType>::type
|
||||
> multiset_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<class VoidAllocator>
|
||||
int test_set_variants()
|
||||
{
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::set_type MySet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
|
||||
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
|
||||
typedef typename GetAllocatorSet<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
|
||||
|
||||
typedef std::set<int> MyStdSet;
|
||||
typedef std::multiset<int> MyStdMultiSet;
|
||||
|
||||
if (0 != test::set_test<
|
||||
MySet
|
||||
,MyStdSet
|
||||
,MyMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyMoveSet
|
||||
,MyStdSet
|
||||
,MyMoveMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyCopyMoveSet
|
||||
,MyStdSet
|
||||
,MyCopyMoveMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 != test::set_test<
|
||||
MyCopySet
|
||||
,MyStdSet
|
||||
,MyCopyMultiSet
|
||||
,MyStdMultiSet>()){
|
||||
std::cout << "Error in set_test<MyBoostSet>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
//Recursive container instantiation
|
||||
{
|
||||
set<recursive_set> set_;
|
||||
multiset<recursive_multiset> multiset_;
|
||||
}
|
||||
//Allocator argument container
|
||||
{
|
||||
set<int> set_((std::allocator<int>()));
|
||||
multiset<int> multiset_((std::allocator<int>()));
|
||||
}
|
||||
//Now test move semantics
|
||||
{
|
||||
test_move<set<recursive_set> >();
|
||||
test_move<multiset<recursive_multiset> >();
|
||||
}
|
||||
|
||||
if(test_set_variants< std::allocator<void> >()){
|
||||
std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< allocator<void> >()){
|
||||
std::cerr << "test_set_variants< allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< node_allocator<void> >()){
|
||||
std::cerr << "test_set_variants< node_allocator<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(test_set_variants< adaptive_pool<void> >()){
|
||||
std::cerr << "test_set_variants< adaptive_pool<void> > failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!boost::container::test::test_propagate_allocator<tree_propagate_test_wrapper>())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <boost/container/detail/config_end.hpp>
|
||||
Reference in New Issue
Block a user