Default initialization for vector-like containers

Complexity guarantees for associative container constructors and ordered input ranges
Added benchmark for associative containers
Fixes #9166

[SVN r85964]
This commit is contained in:
Ion Gaztañaga
2013-09-26 18:05:25 +00:00
parent 59b2793df7
commit 14f092ab00
39 changed files with 1450 additions and 242 deletions

View File

@@ -31,12 +31,130 @@
#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 T>
class default_init_allocator
: public default_init_allocator_base<0>
{
typedef default_init_allocator_base<0> base_t;
public:
typedef T value_type;
default_init_allocator()
{}
template <class U>
default_init_allocator(default_init_allocator<U>)
{}
T* allocate(std::size_t n)
{
//Initialize memory to a pattern
T *const p = ::new T[n];
unsigned char *puc_raw = reinterpret_cast<unsigned char*>(p);
std::size_t max = sizeof(T)*n;
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 p;
}
void deallocate(T *p, std::size_t)
{ delete[] p; }
};
template<class T>
inline bool check_ascending_byte_pattern(const T&t)
{
const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
const std::size_t max = sizeof(T);
for(std::size_t i = 1; i != max; ++i){
if( (pch[i-1] != ((unsigned char)(pch[i]-1u))) ){
return false;
}
}
return true;
}
template<class T>
inline bool check_descending_byte_pattern(const T&t)
{
const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
const std::size_t max = sizeof(T);
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;
}
template<class V1, class V2>
bool vector_copyable_only(V1 *, V2 *, boost::container::container_detail::false_type)
{
@@ -100,7 +218,7 @@ template<class MyBoostVector>
int vector_test()
{
typedef std::vector<int> MyStdVector;
typedef typename MyBoostVector::value_type IntType;
typedef typename MyBoostVector::value_type IntType;
const int max = 100;
if(!test_range_insertion<MyBoostVector>()){