forked from boostorg/container
Default initialization for vector-like containers
Complexity guarantees for associative container constructors and ordered input ranges Fix for #9166 Added benchmark for associative containers Removed check for old MSVC compilers and #pragma once. [SVN r85970]
This commit is contained in:
@@ -25,6 +25,12 @@ class SimpleAllocator
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
template <class U>
|
||||
SimpleAllocator(SimpleAllocator<U>)
|
||||
: allocate_called_(false)
|
||||
, deallocate_called_(false)
|
||||
{}
|
||||
|
||||
SimpleAllocator()
|
||||
: allocate_called_(false)
|
||||
, deallocate_called_(false)
|
||||
@@ -132,6 +138,13 @@ class ComplexAllocator
|
||||
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
template<class U>
|
||||
void construct(U *p, boost::container::default_init_t)
|
||||
{
|
||||
construct_called_ = true;
|
||||
::new (p) U;
|
||||
}
|
||||
|
||||
//getters
|
||||
bool allocate_called() const
|
||||
{ return allocate_called_; }
|
||||
@@ -157,13 +170,13 @@ class ComplexAllocator
|
||||
|
||||
class copymovable
|
||||
{
|
||||
bool copymoveconstructed_;
|
||||
bool moved_;
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE(copymovable)
|
||||
|
||||
public:
|
||||
|
||||
bool copymoveconstructed_;
|
||||
bool moved_;
|
||||
|
||||
copymovable(int, int, int)
|
||||
: copymoveconstructed_(false), moved_(false)
|
||||
{}
|
||||
@@ -314,6 +327,22 @@ int main()
|
||||
SAllocTraits::select_on_container_copy_construction(s_alloc);
|
||||
|
||||
//construct
|
||||
{
|
||||
copymovable c;
|
||||
c.copymoveconstructed_ = true;
|
||||
c.copymoveconstructed_ = true;
|
||||
CAllocTraits::construct(c_alloc, &c);
|
||||
if(!c_alloc.construct_called() || c.copymoveconstructed() || c.moved()){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
int i = 5;
|
||||
CAllocTraits::construct(c_alloc, &i, boost::container::default_init);
|
||||
if(!c_alloc.construct_called() || i != 5){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
copymovable c;
|
||||
copymovable c2;
|
||||
@@ -330,6 +359,22 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
copymovable c;
|
||||
c.copymoveconstructed_ = true;
|
||||
c.copymoveconstructed_ = true;
|
||||
SAllocTraits::construct(s_alloc, &c);
|
||||
if(c.copymoveconstructed() || c.moved()){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
int i = 4;
|
||||
SAllocTraits::construct(s_alloc, &i, boost::container::default_init);
|
||||
if(i != 4){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
copymovable c;
|
||||
copymovable c2;
|
||||
|
||||
@@ -332,6 +332,10 @@ int main ()
|
||||
return 1;
|
||||
if(test::vector_test<MyCopyDeque>())
|
||||
return 1;
|
||||
if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){
|
||||
std::cerr << "Default init test failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if (defined _MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
|
||||
#define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if (defined _MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP
|
||||
#define BOOST_CONTAINER_HEAP_ALLOCATOR_V1_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
#if (defined _MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
|
||||
@@ -66,6 +66,36 @@ void recursive_vector_test()//Test for recursive types
|
||||
}
|
||||
}
|
||||
|
||||
bool default_init_test()//Test for default initialization
|
||||
{
|
||||
typedef stable_vector<int, test::default_init_allocator<int> > svector_t;
|
||||
|
||||
const std::size_t Capacity = 100;
|
||||
|
||||
{
|
||||
test::default_init_allocator<int>::reset_pattern(0);
|
||||
svector_t v(Capacity, default_init);
|
||||
svector_t::iterator it = v.begin();
|
||||
//Compare with the pattern
|
||||
for(std::size_t i = 0; i != Capacity; ++i, ++it){
|
||||
if(*it != static_cast<int>(i))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
{
|
||||
test::default_init_allocator<int>::reset_pattern(100);
|
||||
svector_t v;
|
||||
v.resize(Capacity, default_init);
|
||||
svector_t::iterator it = v.begin();
|
||||
//Compare with the pattern
|
||||
for(std::size_t i = 0; i != Capacity; ++i, ++it){
|
||||
if(*it != static_cast<int>(i+100))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
recursive_vector_test();
|
||||
@@ -102,6 +132,11 @@ int main()
|
||||
if(test::vector_test<MyCopyVector>())
|
||||
return 1;
|
||||
|
||||
if(!test::default_init_test< stable_vector<int, test::default_init_allocator<int> > >()){
|
||||
std::cerr << "Default init test failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
|
||||
if(!boost::container::test::test_emplace
|
||||
< stable_vector<test::EmplaceInt>, Options>())
|
||||
|
||||
@@ -611,6 +611,53 @@ void test_sv_elem(T const& t)
|
||||
v.emplace_back(N/2, t);
|
||||
}
|
||||
|
||||
bool default_init_test()//Test for default initialization
|
||||
{
|
||||
typedef static_vector<int, 100> di_vector_t;
|
||||
|
||||
const std::size_t Capacity = 100;
|
||||
|
||||
{
|
||||
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 stilll 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;
|
||||
@@ -727,6 +774,9 @@ int main(int, char* [])
|
||||
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);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,10 @@ int main()
|
||||
return 1;
|
||||
if(test_expand_bwd())
|
||||
return 1;
|
||||
if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){
|
||||
std::cerr << "Default init test failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
MyEnumVector v;
|
||||
Test t;
|
||||
|
||||
+119
-1
@@ -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>()){
|
||||
|
||||
Reference in New Issue
Block a user