diff --git a/doc/container.qbk b/doc/container.qbk index f8c64ce..1595367 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1086,6 +1086,8 @@ use [*Boost.Container]? There are several reasons for that: and [*Boost.Intrusive]. Preprocessed code size have decreased considerably and compilation times have improved. * Added `nth` and `index_of` functions to containers with random-access iterators (except `basic_string`). * Added C++17's `allocator_traits::is_always_equal`. +* Updated containers to implement new constructors from C++14 (`Sequence(size_type, const allocator_type &)`, and related + constructors in set/map). * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/10790 Trac #10790 (['long long errors from container"])]. * [@https://svn.boost.org/trac/boost/ticket/10808 Trac #10808 (['compare equal operator of vector is broken"])]. diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index b3c5673..632beb5 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -548,7 +548,7 @@ class deque : protected deque_base : Base(a) {} - //! Effects: Constructs a deque that will use a copy of allocator a + //! Effects: Constructs a deque //! and inserts n value initialized values. //! //! Throws: If allocator_type's default constructor @@ -563,6 +563,38 @@ class deque : protected deque_base //deque_base will deallocate in case of exception... } + //! Effects: Constructs a deque + //! and inserts n default initialized values. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default initialization or copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Non-standard extension + deque(size_type n, default_init_t) + : Base(n, allocator_type()) + { + container_detail::insert_default_initialized_n_proxy proxy; + proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); + //deque_base will deallocate in case of exception... + } + + //! Effects: Constructs a deque that will use a copy of allocator a + //! and inserts n value initialized values. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's value initialization throws. + //! + //! Complexity: Linear to n. + explicit deque(size_type n, const allocator_type &a) + : Base(n, a) + { + container_detail::insert_value_initialized_n_proxy proxy; + proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); + //deque_base will deallocate in case of exception... + } + //! Effects: Constructs a deque that will use a copy of allocator a //! and inserts n default initialized values. //! @@ -572,8 +604,8 @@ class deque : protected deque_base //! Complexity: Linear to n. //! //! Note: Non-standard extension - deque(size_type n, default_init_t) - : Base(n, allocator_type()) + deque(size_type n, default_init_t, const allocator_type &a) + : Base(n, a) { container_detail::insert_default_initialized_n_proxy proxy; proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index b717f1a..cd14491 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -222,6 +222,19 @@ class flat_map BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty flat_map using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_map(InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(true, first, last, Compare(), container_detail::force(a)) + { + //A type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty flat_map using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -1218,6 +1231,19 @@ class flat_multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty flat_multimap using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_multimap(InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(false, first, last, Compare(), container_detail::force(a)) + { + //A type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty flat_multimap using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 13a2fab..3924fb0 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -144,6 +144,16 @@ class flat_set : base_t(true, first, last, comp, a) {} + //! Effects: Constructs an empty container using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_set(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(true, first, last, Compare(), a) + {} + //! Effects: Constructs an empty container using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -907,6 +917,12 @@ class flat_multiset : base_t(false, first, last, comp, a) {} + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&) + template + flat_multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, Compare(), a) + {} + //! Effects: Constructs an empty flat_multiset using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last ). This function //! is more efficient than the normal range creation for ordered ranges. diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index d9bd939..b24c48f 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -201,8 +201,8 @@ class list : AllocHolder(a) {} - //! Effects: Constructs a list that will use a copy of allocator a - //! and inserts n copies of value. + //! Effects: Constructs a list + //! and inserts n value-initialized value_types. //! //! Throws: If allocator_type's default constructor //! throws or T's default or copy constructor throws. @@ -212,6 +212,17 @@ class list : AllocHolder(Allocator()) { this->resize(n); } + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + //! Effects: Constructs a list that will use a copy of allocator a //! and inserts n copies of value. //! diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index 6d757c7..bddfb1c 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -175,6 +175,19 @@ class map BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty map using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + map(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(true, first, last, Compare(), a) + { + //A type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty map using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -983,6 +996,19 @@ class multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty multimap using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + multimap(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, Compare(), a) + { + //A type must be std::pair + BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); + } + //! Effects: Constructs an empty multimap using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 8fa8792..f492608 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -141,6 +141,16 @@ class set : base_t(true, first, last, comp, a) {} + //! Effects: Constructs an empty set using the specified + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + set(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(true, first, last, key_compare(), a) + {} + //! Effects: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -787,6 +797,12 @@ class multiset : base_t(false, first, last, comp, a) {} + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&) + template + multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, key_compare(), a) + {} + //! Effects: Constructs an empty multiset using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last ). This function //! is more efficient than the normal range creation for ordered ranges. diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 1867171..b85a335 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -229,10 +229,28 @@ class slist : AllocHolder(a) {} + //! Effects: Constructs a list + //! and inserts n value-initialized value_types. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. explicit slist(size_type n) : AllocHolder(allocator_type()) { this->resize(n); } + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + slist(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + //! Effects: Constructs a list that will use a copy of allocator a //! and inserts n copies of value. //! diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 07a0ed5..85a6b22 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -557,7 +557,7 @@ class stable_vector STABLE_VECTOR_CHECK_INVARIANT; } - //! Effects: Constructs a stable_vector that will use a copy of allocator a + //! Effects: Constructs a stable_vector //! and inserts n value initialized values. //! //! Throws: If allocator_type's default constructor @@ -573,6 +573,40 @@ class stable_vector cod.release(); } + //! Effects: Constructs a stable_vector + //! and inserts n default initialized values. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Non-standard extension + stable_vector(size_type n, default_init_t) + : internal_data(), index() + { + stable_vector_detail::clear_on_destroy cod(*this); + this->resize(n, default_init); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! Effects: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n value initialized values. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit stable_vector(size_type n, const allocator_type &a) + : internal_data(), index(a) + { + stable_vector_detail::clear_on_destroy cod(*this); + this->resize(n); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + //! Effects: Constructs a stable_vector that will use a copy of allocator a //! and inserts n default initialized values. //! @@ -582,8 +616,8 @@ class stable_vector //! Complexity: Linear to n. //! //! Note: Non-standard extension - stable_vector(size_type n, default_init_t) - : internal_data(), index() + stable_vector(size_type n, default_init_t, const allocator_type &a) + : internal_data(), index(a) { stable_vector_detail::clear_on_destroy cod(*this); this->resize(n, default_init); diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj index 0552f5a..5187216 100644 --- a/proj/vc7ide/container.vcproj +++ b/proj/vc7ide/container.vcproj @@ -375,6 +375,9 @@ + + @@ -405,6 +408,9 @@ + + ::reset_pattern(0); + test::default_init_allocator::set_ascending(true); + IntDefaultInitAllocVector v(Capacity, default_init, test::default_init_allocator()); + 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::reset_pattern(100); test::default_init_allocator::set_ascending(false); diff --git a/test/list_test.hpp b/test/list_test.hpp index c4eca93..a6dd04c 100644 --- a/test/list_test.hpp +++ b/test/list_test.hpp @@ -148,6 +148,17 @@ int list_test (bool copied_allocators_equal = true) const int max = 100; typedef list_push_data_function push_data_t; + { //List(n) + ::boost::movelib::unique_ptr const pboostlist = ::boost::movelib::make_unique(100); + ::boost::movelib::unique_ptr const pstdlist = ::boost::movelib::make_unique(100); + if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1; + } + { //List(n, alloc) + ::boost::movelib::unique_ptr const pboostlist = ::boost::movelib::make_unique(100, typename MyBoostList::allocator_type()); + ::boost::movelib::unique_ptr const pstdlist = ::boost::movelib::make_unique(100); + if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1; + } + ::boost::movelib::unique_ptr const pboostlist = ::boost::movelib::make_unique(); ::boost::movelib::unique_ptr const pstdlist = ::boost::movelib::make_unique(); diff --git a/test/map_test.hpp b/test/map_test.hpp index 2dbd558..864db8f 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -133,6 +133,80 @@ int map_test() typedef container_detail::pair IntPairType; typedef typename MyStdMap::value_type StdPairType; const int max = 50; + typedef typename MyStdMap::value_type StdValueType; + typedef typename MyStdMap::key_type StdKeyType; + typedef typename MyStdMap::mapped_type StdMappedType; + + + //Test construction from a range + { + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + ::boost::movelib::unique_ptr const pboostmap = ::boost::movelib::make_unique + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(&aux_vect[0] + 50), typename MyBoostMap::key_compare()); + ::boost::movelib::unique_ptr const pstdmap = ::boost::movelib::make_unique + (&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); + if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1; + + ::boost::movelib::unique_ptr const pboostmultimap = ::boost::movelib::make_unique + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(&aux_vect3[0] + 50), typename MyBoostMap::key_compare()); + ::boost::movelib::unique_ptr const pstdmultimap = ::boost::movelib::make_unique + (&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); + if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1; + } + { + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType i1(i/2); + IntType i2(i/2); + new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + ::boost::movelib::unique_ptr const pboostmap = ::boost::movelib::make_unique + ( boost::make_move_iterator(&aux_vect[0]) + , boost::make_move_iterator(&aux_vect[0] + 50), typename MyBoostMap::allocator_type()); + ::boost::movelib::unique_ptr const pstdmap = ::boost::movelib::make_unique + (&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); + if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1; + + ::boost::movelib::unique_ptr const pboostmultimap = ::boost::movelib::make_unique + ( boost::make_move_iterator(&aux_vect3[0]) + , boost::make_move_iterator(&aux_vect3[0] + 50), typename MyBoostMap::allocator_type()); + ::boost::movelib::unique_ptr const pstdmultimap = ::boost::movelib::make_unique + (&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); + if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1; + } ::boost::movelib::unique_ptr const pboostmap = ::boost::movelib::make_unique(); ::boost::movelib::unique_ptr const pstdmap = ::boost::movelib::make_unique(); @@ -143,7 +217,6 @@ int map_test() MyBoostMultiMap &boostmultimap = *pboostmultimap; MyStdMultiMap &stdmultimap = *pstdmultimap; - //Test construction from a range { //This is really nasty, but we have no other simple choice IntPairType aux_vect[50]; diff --git a/test/set_test.hpp b/test/set_test.hpp index 409de62..554ca6e 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -127,6 +127,54 @@ int set_test () MyStdMultiSet &stdmultiset = *pstdmultiset; //Test construction from a range + { //Set(beg, end, compare) + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i/2; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect3[i] = boost::move(move_me); + } + ::boost::movelib::unique_ptr const pboostset = ::boost::movelib::make_unique + (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::key_compare()); + ::boost::movelib::unique_ptr const pstdset = ::boost::movelib::make_unique(&aux_vect2[0], &aux_vect2[0]+50); + if(!test::CheckEqualContainers(*pboostset, *pstdset)) return 1; + ::boost::movelib::unique_ptr const pboostmultiset = ::boost::movelib::make_unique + (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::key_compare()); + ::boost::movelib::unique_ptr const pstdmultiset = ::boost::movelib::make_unique(&aux_vect2[0], &aux_vect2[0]+50); + if(!test::CheckEqualContainers(*pboostmultiset, *pstdmultiset)) return 1; + } + { //Set(beg, end, alloc) + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect[i] = boost::move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = i/2; + } + IntType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(i/2); + aux_vect3[i] = boost::move(move_me); + } + ::boost::movelib::unique_ptr const pboostset = ::boost::movelib::make_unique + (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::allocator_type()); + ::boost::movelib::unique_ptr const pstdset = ::boost::movelib::make_unique(&aux_vect2[0], &aux_vect2[0]+50); + if(!test::CheckEqualContainers(*pboostset, *pstdset)) return 1; + ::boost::movelib::unique_ptr const pboostmultiset = ::boost::movelib::make_unique + (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::allocator_type()); + ::boost::movelib::unique_ptr const pstdmultiset = ::boost::movelib::make_unique(&aux_vect2[0], &aux_vect2[0]+50); + if(!test::CheckEqualContainers(*pboostmultiset, *pstdmultiset)) return 1; + } { IntType aux_vect[50]; for(int i = 0; i < 50; ++i){ diff --git a/test/vector_test.hpp b/test/vector_test.hpp index b2b55a7..e5c8045 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -113,6 +113,16 @@ int vector_test() if(!test_range_insertion()){ return 1; } + { //Vector(n) + ::boost::movelib::unique_ptr const boostvectorp = ::boost::movelib::make_unique(100); + ::boost::movelib::unique_ptr const stdvectorp = ::boost::movelib::make_unique(100); + if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1; + } + { //Vector(n, alloc) + ::boost::movelib::unique_ptr const boostvectorp = ::boost::movelib::make_unique(100, typename MyBoostVector::allocator_type()); + ::boost::movelib::unique_ptr const stdvectorp = ::boost::movelib::make_unique(100); + if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1; + } { ::boost::movelib::unique_ptr const boostvectorp = ::boost::movelib::make_unique();