diff --git a/doc/container.qbk b/doc/container.qbk index ff18ba4..2c66420 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2009-2012 Ion Gazta\u00F1aga + / Copyright (c) 2009-2013 Ion Gazta\u00F1aga / / 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) @@ -8,7 +8,7 @@ [library Boost.Container [quickbook 1.5] [authors [Gaztanaga, Ion]] - [copyright 2009-2012 Ion Gaztanaga] + [copyright 2009-2013 Ion Gaztanaga] [id container] [dirname container] [purpose Containers library] @@ -67,6 +67,8 @@ compiler include path. [endsect] +[section:main_features Main features] + [section:move_emplace Efficient insertion] Move semantics and placement insertion are two features brought by C++11 containers @@ -189,6 +191,45 @@ Finally, we can just compile, link, and run! [endsect] +[section:scary_iterators SCARY iterators] + +The paper N2913, titled [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2913.pdf, +SCARY Iterator Assignment and Initialization], proposed a requirement that a standard container's +iterator types have no dependency on any type argument apart from the container's `value_type`, +`difference_type`, `pointer type`, and `const_pointer` type. In particular, according to the proposal, +the types of a standard container's iterators should not depend on the container's `key_compare`, +`hasher`, `key_equal`, or `allocator` types. + +That paper demonstrated that SCARY operations were crucial to the performant implementation of common +design patterns using STL components. It showed that implementations that support SCARY operations reduce +object code bloat by eliminating redundant specializations of iterator and algorithm templates. + +[*Boost.Container] containers implement SCARY iterators so the iterator type of a container is only dependent +on the `allocator_traits::pointer` type (the pointer type of the `value_type` to be inserted +in the container). Reference types and all other typedefs are deduced from the pointer type using the +C++11 `pointer_traits` utility. This leads to lower code bloat in algorithms and classes templated on +iterators. + +[endsect] + +[section:other_features Other features] + +* Default constructors don't allocate memory which improves performance and + usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). + +* Small string optimization for [classref boost::container::basic_string basic_string], + with an internal buffer of 11/23 bytes (32/64 bit systems) + [*without] increasing the usual `sizeof` of the string (3 words). + +* `[multi]set/map` containers are size optimized embedding the color bit of the red-black tree nodes + in the parent pointer. + +* `[multi]set/map` containers use no recursive functions so stack problems are avoided. + +[endsect] + +[endsect] + [section:exception_handling Boost.Container and C++ exceptions] In some environments, such as game development or embedded systems, C++ exceptions are disabled or a customized error handling is needed. @@ -375,7 +416,8 @@ and erasure times considerably. Flat associative containers have the following attributes: * Faster lookup than standard associative containers -* Much faster iteration than standard associative containers +* Much faster iteration than standard associative containers. + Random-access iterators instead of bidirectional iterators. * Less memory consumption for small objects (and for big objects if `shrink_to_fit` is used) * Improved cache performance (data is stored in contiguous memory) * Non-stable iterators (iterators are invalidated when inserting and erasing elements) @@ -524,7 +566,7 @@ elements' elements, and so on. [*Boost.Container] implements its own `scoped_allocator_adaptor` class and [*backports this feature also to C++03 compilers]. Due to C++03 limitations, in those compilers the allocator propagation implemented by `scoped_allocator_adaptor::construct` functions -will be based on traits([classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] +will be based on traits ([classref boost::container::constructible_with_allocator_suffix constructible_with_allocator_suffix] and [classref boost::container::constructible_with_allocator_prefix constructible_with_allocator_prefix]) proposed in [@http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2008/n2554.pdf N2554: The Scoped Allocator Model (Rev 2) proposal]. In conforming C++11 compilers or compilers supporting SFINAE @@ -581,22 +623,6 @@ If you need a memory optimized version of `boost::container::vector` funct [endsect] -[section:other_features Other features] - -* Default constructors don't allocate memory which improves performance and - usually implies a no-throw guarantee (if predicate's or allocator's default constructor doesn't throw). - -* Small string optimization for [classref boost::container::basic_string basic_string], - with an internal buffer of 11/23 bytes (32/64 bit systems) - [*without] increasing the usual `sizeof` of the string (3 words). - -* `[multi]set/map` containers are size optimized embedding the color bit of the red-black tree nodes - in the parent pointer. - -* `[multi]set/map` containers use no recursive functions so stack problems are avoided. - -[endsect] - [section:history_and_reasons History and reasons to use Boost.Container] [section:boost_container_history Boost.Container history] @@ -688,6 +714,16 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes Release Notes] +[section:release_notes_boost_1_55_00 Boost 1.55 Release] + +* Implemented [link container.main_features.scary_iterators SCARY iterators]. + +* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/8892 #8892], + [@https://svn.boost.org/trac/boost/ticket/8473 #8473], + [@https://svn.boost.org/trac/boost/ticket/8269 #8269]. + +[endsect] + [section:release_notes_boost_1_54_00 Boost 1.54 Release] * Added experimental `static_vector` class, based on Andrew Hundt's and Adam Wulkiewicz's diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 5ff423d..986b62f 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -75,11 +75,10 @@ template #endif class deque; -template +template struct deque_value_traits { typedef T value_type; - typedef Allocator allocator_type; static const bool trivial_dctr = boost::has_trivial_destructor::value; static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; static const bool trivial_copy = has_trivial_copy::value; @@ -91,13 +90,211 @@ struct deque_value_traits // Note: this function is simply a kludge to work around several compilers' // bugs in handling constant expressions. -inline std::size_t deque_buf_size(std::size_t size) - { return size < 512 ? std::size_t(512 / size) : std::size_t(1); } +template +struct deque_buf_size +{ + static const std::size_t min_size = 512u; + static const std::size_t sizeof_t = sizeof(T); + static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1); +}; + +namespace container_detail { + +// Class invariants: +// For any nonsingular iterator i: +// i.node is the address of an element in the map array. The +// contents of i.node is a pointer to the beginning of a node. +// i.first == //(i.node) +// i.last == i.first + node_size +// i.cur is a pointer in the range [i.first, i.last). NOTE: +// the implication of this is that i.cur is always a dereferenceable +// pointer, even if i is a past-the-end iterator. +// Start and Finish are always nonsingular iterators. NOTE: this means +// that an empty deque must have one node, and that a deque +// with N elements, where N is the buffer size, must have two nodes. +// For every node other than start.node and finish.node, every element +// in the node is an initialized object. If start.node == finish.node, +// then [start.cur, finish.cur) are initialized objects, and +// the elements outside that range are uninitialized storage. Otherwise, +// [start.cur, start.last) and [finish.first, finish.cur) are initialized +// objects, and [start.first, start.cur) and [finish.cur, finish.last) +// are uninitialized storage. +// [map, map + map_size) is a valid, non-empty range. +// [start.node, finish.node] is a valid range contained within +// [map, map + map_size). +// Allocator pointer in the range [map, map + map_size) points to an allocated node +// if and only if the pointer is in the range [start.node, finish.node]. +template +class deque_iterator +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename boost::intrusive::pointer_traits::element_type value_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + static std::size_t s_buffer_size() + { return deque_buf_size::value; } + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type index_pointer; + + Pointer m_cur; + Pointer m_first; + Pointer m_last; + index_pointer m_node; + + public: + + Pointer get_cur() const { return m_cur; } + Pointer get_first() const { return m_first; } + Pointer get_last() const { return m_last; } + index_pointer get_node() const { return m_node; } + + deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_CONTAINER_NOEXCEPT + : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) + {} + + deque_iterator() BOOST_CONTAINER_NOEXCEPT + : m_cur(), m_first(), m_last(), m_node() + {} + + deque_iterator(deque_iterator const& x) BOOST_CONTAINER_NOEXCEPT + : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) + {} + + deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_CONTAINER_NOEXCEPT + : m_cur(cur), m_first(first), m_last(last), m_node(node) + {} + + deque_iterator unconst() const BOOST_CONTAINER_NOEXCEPT + { + return deque_iterator(this->get_cur(), this->get_first(), this->get_last(), this->get_node()); + } + + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return *this->m_cur; } + + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return this->m_cur; } + + difference_type operator-(const deque_iterator& x) const BOOST_CONTAINER_NOEXCEPT + { + if(!this->m_cur && !x.m_cur){ + return 0; + } + return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + + (this->m_cur - this->m_first) + (x.m_last - x.m_cur); + } + + deque_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + { + ++this->m_cur; + if (this->m_cur == this->m_last) { + this->priv_set_node(this->m_node + 1); + this->m_cur = this->m_first; + } + return *this; + } + + deque_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { + deque_iterator tmp(*this); + ++*this; + return tmp; + } + + deque_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + { + if (this->m_cur == this->m_first) { + this->priv_set_node(this->m_node - 1); + this->m_cur = this->m_last; + } + --this->m_cur; + return *this; + } + + deque_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { + deque_iterator tmp(*this); + --*this; + return tmp; + } + + deque_iterator& operator+=(difference_type n) BOOST_CONTAINER_NOEXCEPT + { + difference_type offset = n + (this->m_cur - this->m_first); + if (offset >= 0 && offset < difference_type(this->s_buffer_size())) + this->m_cur += n; + else { + difference_type node_offset = + offset > 0 ? offset / difference_type(this->s_buffer_size()) + : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; + this->priv_set_node(this->m_node + node_offset); + this->m_cur = this->m_first + + (offset - node_offset * difference_type(this->s_buffer_size())); + } + return *this; + } + + deque_iterator operator+(difference_type n) const BOOST_CONTAINER_NOEXCEPT + { deque_iterator tmp(*this); return tmp += n; } + + deque_iterator& operator-=(difference_type n) BOOST_CONTAINER_NOEXCEPT + { return *this += -n; } + + deque_iterator operator-(difference_type n) const BOOST_CONTAINER_NOEXCEPT + { deque_iterator tmp(*this); return tmp -= n; } + + reference operator[](difference_type n) const BOOST_CONTAINER_NOEXCEPT + { return *(*this + n); } + + friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_cur == r.m_cur; } + + friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_cur != r.m_cur; } + + friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } + + friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return r < l; } + + friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(r < l); } + + friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(l < r); } + + void priv_set_node(index_pointer new_node) BOOST_CONTAINER_NOEXCEPT + { + this->m_node = new_node; + this->m_first = *new_node; + this->m_last = this->m_first + this->s_buffer_size(); + } + + friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_CONTAINER_NOEXCEPT + { return x += n; } +}; + +} //namespace container_detail { // Deque base class. It has two purposes. First, its constructor // and destructor allocate (but don't initialize) storage. This makes // exception safety easier. -template +template class deque_base { BOOST_COPYABLE_AND_MOVABLE(deque_base) @@ -124,257 +321,26 @@ class deque_base protected: - typedef deque_value_traits traits_t; - typedef ptr_alloc_t map_allocator_type; + typedef deque_value_traits traits_t; + typedef ptr_alloc_t map_allocator_type; - static size_type s_buffer_size() { return deque_buf_size(sizeof(T)); } + static size_type s_buffer_size() BOOST_CONTAINER_NOEXCEPT + { return deque_buf_size::value; } val_alloc_ptr priv_allocate_node() { return this->alloc().allocate(s_buffer_size()); } - void priv_deallocate_node(val_alloc_ptr p) + void priv_deallocate_node(val_alloc_ptr p) BOOST_CONTAINER_NOEXCEPT { this->alloc().deallocate(p, s_buffer_size()); } ptr_alloc_ptr priv_allocate_map(size_type n) { return this->ptr_alloc().allocate(n); } - void priv_deallocate_map(ptr_alloc_ptr p, size_type n) + void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_CONTAINER_NOEXCEPT { this->ptr_alloc().deallocate(p, n); } - public: - // Class invariants: - // For any nonsingular iterator i: - // i.node is the address of an element in the map array. The - // contents of i.node is a pointer to the beginning of a node. - // i.first == //(i.node) - // i.last == i.first + node_size - // i.cur is a pointer in the range [i.first, i.last). NOTE: - // the implication of this is that i.cur is always a dereferenceable - // pointer, even if i is a past-the-end iterator. - // Start and Finish are always nonsingular iterators. NOTE: this means - // that an empty deque must have one node, and that a deque - // with N elements, where N is the buffer size, must have two nodes. - // For every node other than start.node and finish.node, every element - // in the node is an initialized object. If start.node == finish.node, - // then [start.cur, finish.cur) are initialized objects, and - // the elements outside that range are uninitialized storage. Otherwise, - // [start.cur, start.last) and [finish.first, finish.cur) are initialized - // objects, and [start.first, start.cur) and [finish.cur, finish.last) - // are uninitialized storage. - // [map, map + map_size) is a valid, non-empty range. - // [start.node, finish.node] is a valid range contained within - // [map, map + map_size). - // Allocator pointer in the range [map, map + map_size) points to an allocated node - // if and only if the pointer is in the range [start.node, finish.node]. - class const_iterator - : public std::iterator - { - public: - static size_type s_buffer_size() { return deque_base::s_buffer_size(); } - - typedef std::random_access_iterator_tag iterator_category; - typedef val_alloc_val value_type; - typedef val_alloc_cptr pointer; - typedef val_alloc_cref reference; - typedef val_alloc_diff difference_type; - - typedef ptr_alloc_ptr index_pointer; - typedef const_iterator self_t; - - friend class deque; - friend class deque_base; - - protected: - val_alloc_ptr m_cur; - val_alloc_ptr m_first; - val_alloc_ptr m_last; - index_pointer m_node; - - public: - const_iterator(val_alloc_ptr x, index_pointer y) - : m_cur(x), m_first(*y), - m_last(*y + s_buffer_size()), m_node(y) {} - - const_iterator() : m_cur(0), m_first(0), m_last(0), m_node(0) {} - - const_iterator(const const_iterator& x) - : m_cur(x.m_cur), m_first(x.m_first), - m_last(x.m_last), m_node(x.m_node) {} - - reference operator*() const - { return *this->m_cur; } - - pointer operator->() const - { return this->m_cur; } - - difference_type operator-(const self_t& x) const - { - if(!this->m_cur && !x.m_cur){ - return 0; - } - return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + - (this->m_cur - this->m_first) + (x.m_last - x.m_cur); - } - - self_t& operator++() - { - ++this->m_cur; - if (this->m_cur == this->m_last) { - this->priv_set_node(this->m_node + 1); - this->m_cur = this->m_first; - } - return *this; - } - - self_t operator++(int) - { - self_t tmp = *this; - ++*this; - return tmp; - } - - self_t& operator--() - { - if (this->m_cur == this->m_first) { - this->priv_set_node(this->m_node - 1); - this->m_cur = this->m_last; - } - --this->m_cur; - return *this; - } - - self_t operator--(int) - { - self_t tmp = *this; - --*this; - return tmp; - } - - self_t& operator+=(difference_type n) - { - difference_type offset = n + (this->m_cur - this->m_first); - if (offset >= 0 && offset < difference_type(this->s_buffer_size())) - this->m_cur += n; - else { - difference_type node_offset = - offset > 0 ? offset / difference_type(this->s_buffer_size()) - : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; - this->priv_set_node(this->m_node + node_offset); - this->m_cur = this->m_first + - (offset - node_offset * difference_type(this->s_buffer_size())); - } - return *this; - } - - self_t operator+(difference_type n) const - { self_t tmp = *this; return tmp += n; } - - self_t& operator-=(difference_type n) - { return *this += -n; } - - self_t operator-(difference_type n) const - { self_t tmp = *this; return tmp -= n; } - - reference operator[](difference_type n) const - { return *(*this + n); } - - bool operator==(const self_t& x) const - { return this->m_cur == x.m_cur; } - - bool operator!=(const self_t& x) const - { return !(*this == x); } - - bool operator<(const self_t& x) const - { - return (this->m_node == x.m_node) ? - (this->m_cur < x.m_cur) : (this->m_node < x.m_node); - } - - bool operator>(const self_t& x) const - { return x < *this; } - - bool operator<=(const self_t& x) const - { return !(x < *this); } - - bool operator>=(const self_t& x) const - { return !(*this < x); } - - void priv_set_node(index_pointer new_node) - { - this->m_node = new_node; - this->m_first = *new_node; - this->m_last = this->m_first + this->s_buffer_size(); - } - - friend const_iterator operator+(difference_type n, const const_iterator& x) - { return x + n; } - }; - - //Deque iterator - class iterator : public const_iterator - { - public: - typedef std::random_access_iterator_tag iterator_category; - typedef val_alloc_val value_type; - typedef val_alloc_ptr pointer; - typedef val_alloc_ref reference; - typedef val_alloc_diff difference_type; - typedef ptr_alloc_ptr index_pointer; - typedef const_iterator self_t; - - friend class deque; - friend class deque_base; - - private: - explicit iterator(const const_iterator& x) : const_iterator(x){} - - public: - //Constructors - iterator(val_alloc_ptr x, index_pointer y) : const_iterator(x, y){} - iterator() : const_iterator(){} - //iterator(const const_iterator &cit) : const_iterator(cit){} - iterator(const iterator& x) : const_iterator(x){} - - //Pointer like operators - reference operator*() const { return *this->m_cur; } - pointer operator->() const { return this->m_cur; } - - reference operator[](difference_type n) const { return *(*this + n); } - - //Increment / Decrement - iterator& operator++() - { this->const_iterator::operator++(); return *this; } - - iterator operator++(int) - { iterator tmp = *this; ++*this; return tmp; } - - iterator& operator--() - { this->const_iterator::operator--(); return *this; } - - iterator operator--(int) - { iterator tmp = *this; --*this; return tmp; } - - // Arithmetic - iterator& operator+=(difference_type off) - { this->const_iterator::operator+=(off); return *this; } - - iterator operator+(difference_type off) const - { return iterator(this->const_iterator::operator+(off)); } - - friend iterator operator+(difference_type off, const iterator& right) - { return iterator(off+static_cast(right)); } - - iterator& operator-=(difference_type off) - { this->const_iterator::operator-=(off); return *this; } - - iterator operator-(difference_type off) const - { return iterator(this->const_iterator::operator-(off)); } - - difference_type operator-(const const_iterator& right) const - { return static_cast(*this) - right; } - }; + typedef container_detail::deque_iterator iterator; + typedef container_detail::deque_iterator const_iterator; deque_base(size_type num_elements, const allocator_type& a) : members_(a) @@ -406,7 +372,7 @@ class deque_base protected: - void swap_members(deque_base &x) + void swap_members(deque_base &x) BOOST_CONTAINER_NOEXCEPT { std::swap(this->members_.m_start, x.members_.m_start); std::swap(this->members_.m_finish, x.members_.m_finish); @@ -458,13 +424,13 @@ class deque_base BOOST_CATCH_END } - void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_CONTAINER_NOEXCEPT { for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) this->priv_deallocate_node(*n); } - void priv_clear_map() + void priv_clear_map() BOOST_CONTAINER_NOEXCEPT { if (this->members_.m_map) { this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); @@ -509,16 +475,16 @@ class deque_base iterator m_finish; } members_; - ptr_alloc_t &ptr_alloc() + ptr_alloc_t &ptr_alloc() BOOST_CONTAINER_NOEXCEPT { return members_; } - const ptr_alloc_t &ptr_alloc() const + const ptr_alloc_t &ptr_alloc() const BOOST_CONTAINER_NOEXCEPT { return members_; } - allocator_type &alloc() + allocator_type &alloc() BOOST_CONTAINER_NOEXCEPT { return members_; } - const allocator_type &alloc() const + const allocator_type &alloc() const BOOST_CONTAINER_NOEXCEPT { return members_; } }; /// @endcond @@ -530,11 +496,11 @@ template > #else template #endif -class deque : protected deque_base +class deque : protected deque_base { /// @cond private: - typedef deque_base Base; + typedef deque_base Base; /// @endcond public: @@ -1397,7 +1363,7 @@ class deque : protected deque_base ) { size_type n = 0; - iterator it(pos); + iterator it(pos.unconst()); for(;first != last; ++first, ++n){ it = this->emplace(it, *first); ++it; @@ -1468,15 +1434,15 @@ class deque : protected deque_base //! Constant if pos is the first or the last element. iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT { - const_iterator next = pos; + iterator next = pos.unconst(); ++next; size_type index = pos - this->members_.m_start; if (index < (this->size()/2)) { - boost::move_backward(begin(), iterator(pos), iterator(next)); + boost::move_backward(this->begin(), pos.unconst(), next); pop_front(); } else { - boost::move(iterator(next), end(), iterator(pos)); + boost::move(next, this->end(), pos.unconst()); pop_back(); } return this->members_.m_start + index; @@ -1500,7 +1466,7 @@ class deque : protected deque_base const size_type n = static_cast(last - first); const size_type elems_before = static_cast(first - this->members_.m_start); if (elems_before < (this->size() - n) - elems_before) { - boost::move_backward(begin(), iterator(first), iterator(last)); + boost::move_backward(begin(), first.unconst(), last.unconst()); iterator new_start = this->members_.m_start + n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(this->members_.m_start, new_start); @@ -1508,7 +1474,7 @@ class deque : protected deque_base this->members_.m_start = new_start; } else { - boost::move(iterator(last), end(), iterator(first)); + boost::move(last.unconst(), end(), first.unconst()); iterator new_finish = this->members_.m_finish - n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(new_finish, this->members_.m_finish); @@ -1674,7 +1640,7 @@ class deque : protected deque_base template iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy interf) { - iterator pos(p); + iterator pos(p.unconst()); const size_type pos_n = p - this->cbegin(); if(!this->members_.m_map){ this->priv_initialize_map(0); @@ -1845,7 +1811,7 @@ class deque : protected deque_base } // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. - void priv_pop_back_aux() + void priv_pop_back_aux() BOOST_CONTAINER_NOEXCEPT { this->priv_deallocate_node(this->members_.m_finish.m_first); this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); @@ -1860,7 +1826,7 @@ class deque : protected deque_base // if the deque has at least one element (a precondition for this member // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque // must have at least two nodes. - void priv_pop_front_aux() + void priv_pop_front_aux() BOOST_CONTAINER_NOEXCEPT { allocator_traits_type::destroy ( this->alloc() @@ -1959,31 +1925,31 @@ class deque : protected deque_base // Nonmember functions. template -inline bool operator==(const deque& x, const deque& y) +inline bool operator==(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); } template -inline bool operator<(const deque& x, const deque& y) +inline bool operator<(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } template -inline bool operator!=(const deque& x, const deque& y) +inline bool operator!=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(x == y); } template -inline bool operator>(const deque& x, const deque& y) +inline bool operator>(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return y < x; } template -inline bool operator>=(const deque& x, const deque& y) +inline bool operator>=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(x < y); } template -inline bool operator<=(const deque& x, const deque& y) +inline bool operator<=(const deque& x, const deque& y) BOOST_CONTAINER_NOEXCEPT { return !(y < x); } template diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 90f0352..896f161 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -85,9 +85,9 @@ struct get_flat_tree_iterators rebind_pointer::type const_iterator; #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER typedef typename container_detail:: - vector_iterator iterator; + vec_iterator iterator; typedef typename container_detail:: - vector_const_iterator const_iterator; + vec_iterator const_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; @@ -115,7 +115,7 @@ class flat_tree : value_compare(), m_vect() {} - Data(const Data &d) + explicit Data(const Data &d) : value_compare(static_cast(d)), m_vect(d.m_vect) {} @@ -131,15 +131,18 @@ class flat_tree : value_compare(boost::move(static_cast(d))), m_vect(boost::move(d.m_vect), a) {} - Data(const Compare &comp) + explicit Data(const Compare &comp) : value_compare(comp), m_vect() {} - Data(const Compare &comp, - const allocator_t &alloc) + Data(const Compare &comp, const allocator_t &alloc) : value_compare(comp), m_vect(alloc) {} + explicit Data(const allocator_t &alloc) + : value_compare(), m_vect(alloc) + {} + Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d) { this->value_compare::operator=(d); @@ -203,6 +206,10 @@ class flat_tree : m_data(comp, a) { } + explicit flat_tree(const allocator_type& a) + : m_data(a) + { } + flat_tree(const flat_tree& x) : m_data(x.m_data) { } diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp index bba7205..03ac6c9 100644 --- a/include/boost/container/detail/iterators.hpp +++ b/include/boost/container/detail/iterators.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef BOOST_CONTAINER_PERFECT_FORWARDING #include @@ -585,24 +586,112 @@ struct is_bidirectional_iterator static const bool value = false; }; -template +template struct iiterator_types { + typedef typename IIterator::value_type it_value_type; + typedef typename it_value_type::value_type value_type; typedef typename std::iterator_traits::pointer it_pointer; typedef typename std::iterator_traits::difference_type difference_type; typedef typename ::boost::intrusive::pointer_traits:: - template rebind_pointer::type pointer; + template rebind_pointer::type pointer; typedef typename ::boost::intrusive::pointer_traits:: - template rebind_pointer::type const_pointer; + template rebind_pointer::type const_pointer; typedef typename ::boost::intrusive:: pointer_traits::reference reference; typedef typename ::boost::intrusive:: pointer_traits::reference const_reference; + typedef typename IIterator::iterator_category iterator_category; }; +template +struct std_iterator +{ + typedef typename std::iterator + < typename iiterator_types::iterator_category + , typename iiterator_types::value_type + , typename iiterator_types::difference_type + , typename iiterator_types::const_pointer + , typename iiterator_types::const_reference> type; +}; + +template +struct std_iterator +{ + typedef typename std::iterator + < typename iiterator_types::iterator_category + , typename iiterator_types::value_type + , typename iiterator_types::difference_type + , typename iiterator_types::pointer + , typename iiterator_types::reference> type; +}; + +template +class iterator + : public std_iterator::type +{ + typedef typename std_iterator::type types_t; + + public: + typedef typename types_t::value_type value_type; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + + iterator() + {} + + explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT + : m_iit(iit) + {} + + iterator(iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_iit(other.get()) + {} + + iterator& operator++() BOOST_CONTAINER_NOEXCEPT + { ++this->m_iit; return *this; } + + iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { + iterator result (*this); + ++this->m_iit; + return result; + } + + iterator& operator--() BOOST_CONTAINER_NOEXCEPT + { + //If the iterator is not a bidirectional iterator, operator-- should not exist + BOOST_STATIC_ASSERT((is_bidirectional_iterator::value)); + --this->m_iit; return *this; + } + + iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { + iterator result (*this); + --this->m_iit; + return result; + } + + friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_iit == r.m_iit; } + + friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return !(l == r); } + + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return (*this->m_iit).get_data(); } + + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return ::boost::intrusive::pointer_traits::pointer_to(this->operator*()); } + + const IIterator &get() const BOOST_CONTAINER_NOEXCEPT + { return this->m_iit; } + + private: + IIterator m_iit; +}; } //namespace container_detail { - } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 5a94a68..4a5052a 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -53,10 +53,14 @@ struct node_compare typedef typename ValueCompare::value_type value_type; typedef typename ValueCompare::key_of_value key_of_value; - node_compare(const ValueCompare &pred) + explicit node_compare(const ValueCompare &pred) : ValueCompare(pred) {} + node_compare() + : ValueCompare() + {} + ValueCompare &value_comp() { return static_cast(*this); } @@ -67,11 +71,10 @@ struct node_compare { return ValueCompare::operator()(a.get_data(), b.get_data()); } }; -template +template struct node_alloc_holder { typedef allocator_traits allocator_traits_type; - typedef node_alloc_holder self_t; typedef typename allocator_traits_type::value_type value_type; typedef typename ICont::value_type Node; typedef typename allocator_traits_type::template @@ -116,20 +119,20 @@ struct node_alloc_holder { this->icont().swap(x.icont()); } //Constructors for associative containers - explicit node_alloc_holder(const ValAlloc &a, const Pred &c) + explicit node_alloc_holder(const ValAlloc &a, const ValPred &c) : members_(a, c) {} - explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c) + explicit node_alloc_holder(const node_alloc_holder &x, const ValPred &c) : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c) {} - explicit node_alloc_holder(const Pred &c) + explicit node_alloc_holder(const ValPred &c) : members_(c) {} //helpers for move assignments - explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const Pred &c) + explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const ValPred &c) : members_(boost::move(x.node_alloc()), c) { this->icont().swap(x.icont()); } @@ -345,12 +348,12 @@ struct node_alloc_holder {} template - members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c) + members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const ValPred &c) : NodeAlloc(boost::forward(c2alloc)) , m_icont(typename ICont::value_compare(c)) {} - explicit members_holder(const Pred &c) + explicit members_holder(const ValPred &c) : NodeAlloc() , m_icont(typename ICont::value_compare(c)) {} diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 9cb3c9f..6dcb1b7 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -20,8 +20,8 @@ #include #include #include - #include +#include #include #include #include @@ -50,8 +50,12 @@ struct tree_value_compare typedef KeyOfValue key_of_value; typedef Key key_type; - tree_value_compare(const key_compare &kcomp) - : key_compare(kcomp) + explicit tree_value_compare(const key_compare &kcomp) + : KeyCompare(kcomp) + {} + + tree_value_compare() + : KeyCompare() {} const key_compare &key_comp() const @@ -212,15 +216,15 @@ class rbtree , typename container_detail::intrusive_rbtree_type >::type - , KeyCompare + , tree_value_compare > { + typedef tree_value_compare + ValComp; typedef typename container_detail::intrusive_rbtree_type - < A, tree_value_compare - - >::type Icont; + < A, ValComp>::type Icont; typedef container_detail::node_alloc_holder - AllocHolder; + AllocHolder; typedef typename AllocHolder::NodePtr NodePtr; typedef rbtree < Key, Value, KeyOfValue , KeyCompare, A> ThisType; @@ -318,8 +322,7 @@ class rbtree typedef Value value_type; typedef A allocator_type; typedef KeyCompare key_compare; - typedef tree_value_compare< Key, Value - , KeyCompare, KeyOfValue> value_compare; + typedef ValComp value_compare; typedef typename boost::container:: allocator_traits::pointer pointer; typedef typename boost::container:: @@ -373,109 +376,21 @@ class rbtree typedef key_node_compare KeyNodeCompare; public: - //rbtree const_iterator - class const_iterator - : public std::iterator - < std::bidirectional_iterator_tag - , value_type , rbtree_difference_type - , rbtree_const_pointer , rbtree_const_reference> - { - protected: - typedef typename Icont::iterator iiterator; - iiterator m_it; - explicit const_iterator(iiterator it) : m_it(it){} - void prot_incr() { ++m_it; } - void prot_decr() { --m_it; } - - private: - iiterator get() - { return this->m_it; } - - public: - friend class rbtree ; - typedef rbtree_difference_type difference_type; - - //Constructors - const_iterator() - : m_it() - {} - - //Pointer like operators - const_reference operator*() const - { return m_it->get_data(); } - - const_pointer operator->() const - { return const_pointer(&m_it->get_data()); } - - //Increment / Decrement - const_iterator& operator++() - { prot_incr(); return *this; } - - const_iterator operator++(int) - { iiterator tmp = m_it; ++*this; return const_iterator(tmp); } - - const_iterator& operator--() - { prot_decr(); return *this; } - - const_iterator operator--(int) - { iiterator tmp = m_it; --*this; return const_iterator(tmp); } - - //Comparison operators - bool operator== (const const_iterator& r) const - { return m_it == r.m_it; } - - bool operator!= (const const_iterator& r) const - { return m_it != r.m_it; } - }; - - //rbtree iterator - class iterator : public const_iterator - { - private: - explicit iterator(iiterator it) - : const_iterator(it) - {} - - iiterator get() - { return this->m_it; } - - public: - friend class rbtree ; - typedef rbtree_pointer pointer; - typedef rbtree_reference reference; - - //Constructors - iterator(){} - - //Pointer like operators - reference operator*() const - { return this->m_it->get_data(); } - pointer operator->() const - { return boost::intrusive::pointer_traits::pointer_to(this->m_it->get_data()); } - - //Increment / Decrement - iterator& operator++() - { this->prot_incr(); return *this; } - - iterator operator++(int) - { iiterator tmp = this->m_it; ++*this; return iterator(tmp); } - - iterator& operator--() - { this->prot_decr(); return *this; } - - iterator operator--(int) - { iterator tmp = *this; --*this; return tmp; } - }; - + typedef container_detail::iterator iterator; + typedef container_detail::iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; rbtree() - : AllocHolder(key_compare()) + : AllocHolder(ValComp(key_compare())) {} - rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) - : AllocHolder(a, comp) + explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) + : AllocHolder(a, ValComp(comp)) + {} + + explicit rbtree(const allocator_type& a) + : AllocHolder(a) {} template @@ -488,7 +403,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { if(unique_insertion){ this->insert_unique(first, last); @@ -508,7 +423,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { if(unique_insertion){ this->insert_unique(first, last); @@ -530,7 +445,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { this->insert_equal(first, last); } @@ -545,7 +460,7 @@ class rbtree >::type * = 0 #endif ) - : AllocHolder(a, comp) + : AllocHolder(a, value_compare(comp)) { //Optimized allocation and construction this->allocate_many_and_construct @@ -553,25 +468,25 @@ class rbtree } rbtree(const rbtree& x) - : AllocHolder(x, x.key_comp()) + : AllocHolder(x, x.value_comp()) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } rbtree(BOOST_RV_REF(rbtree) x) - : AllocHolder(::boost::move(static_cast(x)), x.key_comp()) + : AllocHolder(::boost::move(static_cast(x)), x.value_comp()) {} rbtree(const rbtree& x, const allocator_type &a) - : AllocHolder(a, x.key_comp()) + : AllocHolder(a, x.value_comp()) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a) - : AllocHolder(a, x.key_comp()) + : AllocHolder(a, x.value_comp()) { if(this->node_alloc() == x.node_alloc()){ this->icont().swap(x.icont()); diff --git a/include/boost/container/detail/utilities.hpp b/include/boost/container/detail/utilities.hpp index 81e0ed8..776a770 100644 --- a/include/boost/container/detail/utilities.hpp +++ b/include/boost/container/detail/utilities.hpp @@ -12,6 +12,7 @@ #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP #include "config_begin.hpp" +#include "workaround.hpp" #include #include //for ::memcpy #include @@ -1055,18 +1056,21 @@ inline typename container_detail::enable_if_c ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 3: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 2: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); ::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; + BOOST_CONTAINER_FALLTHOUGH case 1: ::memcpy(stora_ptr, large_ptr, sizeof_storage); ::memcpy(large_ptr, short_ptr, sizeof_storage); diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp index 06cb733..49fe284 100644 --- a/include/boost/container/detail/workaround.hpp +++ b/include/boost/container/detail/workaround.hpp @@ -35,6 +35,12 @@ #define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST #endif +#if !defined(BOOST_FALLTHOUGH) + #define BOOST_CONTAINER_FALLTHOUGH +#else + #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH; +#endif + //Macros for documentation purposes. For code, expands to the argument #define BOOST_CONTAINER_IMPDEF(TYPE) TYPE #define BOOST_CONTAINER_SEEDOC(TYPE) TYPE diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 8bb372f..da992aa 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -84,8 +84,10 @@ static D force_copy(S s) //! This means that inserting a new element into a flat_map invalidates //! previous iterators and references //! -//! Erasing an element of a flat_map invalidates iterators and references +//! Erasing an element invalidates iterators and references //! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator< std::pair< Key, T> > > #else @@ -173,7 +175,15 @@ class flat_map //! //! Complexity: Constant. explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force(a)) {} + : m_flat_tree(comp, container_detail::force(a)) + {} + + //! Effects: Constructs an empty flat_map using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_map(const allocator_type& a) + : m_flat_tree(container_detail::force(a)) + {} //! Effects: Constructs an empty flat_map using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). @@ -939,6 +949,15 @@ inline bool operator<(const flat_multimap& x, //! //! Allocator is the allocator to allocate the value_types //! (e.g. allocator< std::pair >). +//! +//! flat_multimap is similar to std::multimap but it's implemented like an ordered vector. +//! This means that inserting a new element into a flat_map invalidates +//! previous iterators and references +//! +//! Erasing an element invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator< std::pair< Key, T> > > #else @@ -1024,7 +1043,15 @@ class flat_multimap //! Complexity: Constant. explicit flat_multimap(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force(a)) { } + : m_flat_tree(comp, container_detail::force(a)) + {} + + //! Effects: Constructs an empty flat_multimap using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_multimap(const allocator_type& a) + : m_flat_tree(container_detail::force(a)) + {} //! Effects: Constructs an empty flat_multimap using the specified comparison object //! and allocator, and inserts elements from the range [first ,last ). diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 82bdea8..eed7dda 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -51,9 +51,7 @@ inline bool operator<(const flat_set& x, /// @endcond //! flat_set is a Sorted Associative Container that stores objects of type Key. -//! flat_set is a Simple Associative Container, meaning that its value type, -//! as well as its key type, is Key. It is also a Unique Associative Container, -//! meaning that no two elements are the same. +//! It is also a Unique Associative Container, meaning that no two elements are the same. //! //! flat_set is similar to std::set but it's implemented like an ordered vector. //! This means that inserting a new element into a flat_set invalidates @@ -61,6 +59,8 @@ inline bool operator<(const flat_set& x, //! //! Erasing an element of a flat_set invalidates iterators and references //! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator > #else @@ -121,6 +121,13 @@ class flat_set : m_flat_tree(comp, a) {} + //! Effects: Constructs an empty flat_set using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_set(const allocator_type& a) + : m_flat_tree(a) + {} + //! Effects: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! @@ -756,16 +763,17 @@ inline bool operator<(const flat_multiset& x, /// @endcond //! flat_multiset is a Sorted Associative Container that stores objects of type Key. -//! flat_multiset is a Simple Associative Container, meaning that its value type, -//! as well as its key type, is Key. -//! flat_Multiset can store multiple copies of the same key value. +//! +//! flat_multiset can store multiple copies of the same key value. //! //! flat_multiset is similar to std::multiset but it's implemented like an ordered vector. //! This means that inserting a new element into a flat_multiset invalidates //! previous iterators and references //! -//! Erasing an element of a flat_multiset invalidates iterators and references -//! pointing to elements that come after (their keys are equal or bigger) the erased element. +//! Erasing an element invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +//! +//! This container provides random-access iterators. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED template , class Allocator = std::allocator > #else @@ -810,9 +818,21 @@ class flat_multiset : m_flat_tree() {} + //! Effects: Constructs an empty flat_multiset using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. explicit flat_multiset(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, a) {} + : m_flat_tree(comp, a) + {} + + //! Effects: Constructs an empty flat_multiset using the specified allocator. + //! + //! Complexity: Constant. + explicit flat_multiset(const allocator_type& a) + : m_flat_tree(a) + {} template flat_multiset(InputIterator first, InputIterator last, diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 79f4a6b..e613f4a 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -26,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -64,8 +65,16 @@ struct list_node list_node(); public: + typedef T value_type; typedef typename list_hook::type hook_type; + T m_data; + + T &get_data() + { return this->m_data; } + + const T &get_data() const + { return this->m_data; } }; template @@ -89,105 +98,6 @@ struct intrusive_list_type typedef container_type type ; }; -template -class list_const_iterator - : public std::iterator< std::bidirectional_iterator_tag, T - , typename iiterator_types::difference_type - , typename iiterator_types::const_pointer - , typename iiterator_types::const_reference> -{ - protected: - - IIterator m_it; - - public: - typedef typename iiterator_types::const_pointer const_pointer; - typedef typename iiterator_types::const_reference const_reference; - - //Constructors - list_const_iterator() - : m_it() - {} - - explicit list_const_iterator(const IIterator &it) - : m_it(it) - {} - - //Pointer like operators - const_reference operator*() const - { return this->m_it->m_data; } - - const_pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - list_const_iterator& operator++() - { ++this->m_it; return *this; } - - list_const_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return list_const_iterator(tmp); } - - list_const_iterator& operator--() - { --this->m_it; return *this; } - - list_const_iterator operator--(int) - { IIterator tmp = this->m_it; --*this; return list_const_iterator(tmp); } - - //Comparison operators - friend bool operator== (const list_const_iterator& l, const list_const_iterator& r) - { return l.m_it == r.m_it; } - - friend bool operator!= (const list_const_iterator& l, const list_const_iterator& r) - { return l.m_it != r.m_it; } - - const IIterator &get() const - { return this->m_it; } -}; - -template -class list_iterator - : public list_const_iterator -{ - private: - typedef list_const_iterator const_iterator; - - public: - typedef typename iiterator_types::pointer pointer; - typedef typename iiterator_types::reference reference; - - //Constructors - list_iterator() - : const_iterator() - {} - - explicit list_iterator(const IIterator &it) - : const_iterator(it) - {} - - //Pointer like operators - reference operator*() const - { return this->m_it->m_data; } - - pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - list_iterator& operator++() - { ++this->m_it; return *this; } - - list_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return list_iterator(tmp); } - - list_iterator& operator--() - { --this->m_it; return *this; } - - list_iterator operator--(int) - { IIterator tmp = this->m_it; --*this; return list_iterator(tmp); } - - const IIterator &get() const - { return this->m_it; } -}; - } //namespace container_detail { /// @endcond @@ -255,8 +165,8 @@ class list BOOST_COPYABLE_AND_MOVABLE(list) - typedef container_detail::list_iterator iterator_impl; - typedef container_detail::list_const_iteratorconst_iterator_impl; + typedef container_detail::iterator iterator_impl; + typedef container_detail::iterator const_iterator_impl; /// @endcond public: @@ -442,7 +352,6 @@ class list } //If unequal allocators, then do a one by one move else{ - typedef typename std::iterator_traits::iterator_category ItCat; this->assign( boost::make_move_iterator(x.begin()) , boost::make_move_iterator(x.end())); } diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index b1faf49..e6ca865 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -138,6 +138,16 @@ class map BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty map using the specified allocator. + //! + //! Complexity: Constant. + explicit map(const allocator_type& a) + : m_tree(a) + { + //Allocator 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 range [first ,last ). //! @@ -918,8 +928,7 @@ class multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } - //! Effects: Constructs an empty multimap using the specified comparison - //! object and allocator. + //! Effects: Constructs an empty multimap using the specified allocator. //! //! Complexity: Constant. explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()) @@ -929,6 +938,17 @@ class multimap BOOST_STATIC_ASSERT((container_detail::is_same, typename Allocator::value_type>::value)); } + //! Effects: Constructs an empty multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multimap(const allocator_type& a) + : m_tree(a) + { + //Allocator 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 range [first ,last ). //! diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 0b49376..7808859 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -113,6 +113,13 @@ class set : m_tree(comp, a) {} + //! Effects: Constructs an empty set using the specified allocator object. + //! + //! Complexity: Constant. + explicit set(const allocator_type& a) + : m_tree(a) + {} + //! Effects: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! @@ -737,6 +744,13 @@ class multiset : m_tree(comp, a) {} + //! Effects: Constructs an empty multiset using the specified allocator. + //! + //! Complexity: Constant. + explicit multiset(const allocator_type& a) + : m_tree(a) + {} + //! Effects: Constructs an empty multiset using the specified comparison object //! and allocator, and inserts elements from the range [first ,last ). //! diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index a9a4f67..e0aa95f 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -69,8 +70,16 @@ struct slist_node slist_node(); public: + typedef T value_type; typedef typename slist_hook::type hook_type; + T m_data; + + T &get_data() + { return this->m_data; } + + const T &get_data() const + { return this->m_data; } }; template @@ -95,93 +104,6 @@ struct intrusive_slist_type typedef container_type type ; }; -template -class slist_const_iterator - : public std::iterator< std::forward_iterator_tag, T - , typename iiterator_types::difference_type - , typename iiterator_types::const_pointer - , typename iiterator_types::const_reference> -{ - protected: - - IIterator m_it; - - public: - typedef typename iiterator_types::const_pointer const_pointer; - typedef typename iiterator_types::const_reference const_reference; - - //Constructors - slist_const_iterator() - : m_it() - {} - - explicit slist_const_iterator(const IIterator &it) - : m_it(it) - {} - - //Pointer like operators - const_reference operator*() const - { return this->m_it->m_data; } - - const_pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - slist_const_iterator& operator++() - { ++this->m_it; return *this; } - - slist_const_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return slist_const_iterator(tmp); } - - //Comparison operators - friend bool operator== (const slist_const_iterator& l, const slist_const_iterator& r) - { return l.m_it == r.m_it; } - - friend bool operator!= (const slist_const_iterator& l, const slist_const_iterator& r) - { return l.m_it != r.m_it; } - - const IIterator &get() const - { return this->m_it; } -}; - -template -class slist_iterator - : public slist_const_iterator -{ - private: - typedef slist_const_iterator const_iterator; - - public: - typedef typename iiterator_types::pointer pointer; - typedef typename iiterator_types::reference reference; - - //Constructors - slist_iterator() - : const_iterator() - {} - - explicit slist_iterator(const IIterator &it) - : const_iterator(it) - {} - - //Pointer like operators - reference operator*() const - { return this->m_it->m_data; } - - pointer operator->() const - { return ::boost::intrusive::pointer_traits::pointer_to(this->m_it->m_data); } - - //Increment / Decrement - slist_iterator& operator++() - { ++this->m_it; return *this; } - - slist_iterator operator++(int) - { IIterator tmp = this->m_it; ++*this; return slist_iterator(tmp); } - - const IIterator &get() const - { return this->m_it; } -}; - } //namespace container_detail { /// @endcond @@ -271,8 +193,8 @@ class slist }; BOOST_COPYABLE_AND_MOVABLE(slist) - typedef container_detail::slist_iterator iterator_impl; - typedef container_detail::slist_const_iteratorconst_iterator_impl; + typedef container_detail::iterator iterator_impl; + typedef container_detail::iterator const_iterator_impl; /// @endcond public: @@ -451,7 +373,6 @@ class slist } //If unequal allocators, then do a one by one move else{ - typedef typename std::iterator_traits::iterator_category ItCat; this->assign( boost::make_move_iterator(x.begin()) , boost::make_move_iterator(x.end())); } diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 3da8c64..c5353f3 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -88,7 +88,7 @@ class clear_on_destroy bool do_clear_; }; -template +template struct node; template @@ -116,167 +116,172 @@ struct node_base node_base_ptr_ptr up; }; -template +template struct node - : public node_base + : public node_base + ::template + rebind_pointer::type + > { private: node(); public: - T value; + typename ::boost::intrusive::pointer_traits::element_type value; }; -template +template class iterator - : public std::iterator< std::random_access_iterator_tag - , T - , typename boost::intrusive:: - pointer_traits::difference_type - , Pointer - , Reference> { - typedef boost::intrusive:: - pointer_traits ptr_traits; - typedef typename ptr_traits::template + typedef boost::intrusive::pointer_traits non_const_ptr_traits; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename non_const_ptr_traits::element_type value_type; + typedef typename non_const_ptr_traits::difference_type difference_type; + typedef typename ::boost::container::container_detail::if_c + < IsConst + , typename non_const_ptr_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename ::boost::container::container_detail::if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + private: + typedef typename non_const_ptr_traits::template rebind_pointer::type void_ptr; - typedef node node_type; + typedef node node_type; typedef node_base node_base_type; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_ptr; typedef boost::intrusive:: pointer_traits node_ptr_traits; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_base_ptr; - typedef typename ptr_traits::template + typedef typename non_const_ptr_traits::template rebind_pointer::type node_base_ptr_ptr; - typedef typename ptr_traits::template - rebind_pointer::type friend_iterator_pointer; - friend class iterator; + node_ptr m_pn; public: - typedef std::random_access_iterator_tag iterator_category; - typedef T value_type; - typedef typename ptr_traits::difference_type difference_type; - typedef Pointer pointer; - typedef Reference reference; - iterator() + explicit iterator(node_ptr p) BOOST_CONTAINER_NOEXCEPT + : m_pn(p) {} - explicit iterator(node_ptr p) - : pn(p) + iterator() BOOST_CONTAINER_NOEXCEPT {} - iterator(const iterator& x) - : pn(x.pn) + iterator(iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_pn(other.node_pointer()) {} - node_ptr &node_pointer() - { return pn; } + node_ptr &node_pointer() BOOST_CONTAINER_NOEXCEPT + { return m_pn; } - const node_ptr &node_pointer() const - { return pn; } + const node_ptr &node_pointer() const BOOST_CONTAINER_NOEXCEPT + { return m_pn; } public: //Pointer like operators - reference operator*() const - { return pn->value; } + reference operator*() const BOOST_CONTAINER_NOEXCEPT + { return m_pn->value; } - pointer operator->() const - { return ptr_traits::pointer_to(this->operator*()); } + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { + typedef boost::intrusive::pointer_traits ptr_traits; + return ptr_traits::pointer_to(this->operator*()); + } //Increment / Decrement - iterator& operator++() + iterator& operator++() BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ ++p; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - iterator operator++(int) + iterator operator++(int) BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); ++*this; return iterator(tmp); } - iterator& operator--() + iterator& operator--() BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ --p; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - iterator operator--(int) + iterator operator--(int) BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); --*this; return iterator(tmp); } - reference operator[](difference_type off) const + reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT { iterator tmp(*this); tmp += off; return *tmp; } - iterator& operator+=(difference_type off) + iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT { - if(node_base_ptr_ptr p = this->pn->up){ + if(node_base_ptr_ptr p = this->m_pn->up){ p += off; - this->pn = node_ptr_traits::static_cast_from(*p); + this->m_pn = node_ptr_traits::static_cast_from(*p); } return *this; } - friend iterator operator+(const iterator &left, difference_type off) + friend iterator operator+(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT { iterator tmp(left); tmp += off; return tmp; } - friend iterator operator+(difference_type off, const iterator& right) + friend iterator operator+(difference_type off, const iterator& right) BOOST_CONTAINER_NOEXCEPT { iterator tmp(right); tmp += off; return tmp; } - iterator& operator-=(difference_type off) + iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT { *this += -off; return *this; } - friend iterator operator-(const iterator &left, difference_type off) + friend iterator operator-(const iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT { iterator tmp(left); tmp -= off; return tmp; } - friend difference_type operator-(const iterator& left, const iterator& right) - { - return left.pn->up - right.pn->up; - } + friend difference_type operator-(const iterator& left, const iterator& right) BOOST_CONTAINER_NOEXCEPT + { return left.m_pn->up - right.m_pn->up; } //Comparison operators - friend bool operator== (const iterator& l, const iterator& r) - { return l.pn == r.pn; } + friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn == r.m_pn; } - friend bool operator!= (const iterator& l, const iterator& r) - { return l.pn != r.pn; } + friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn != r.m_pn; } - friend bool operator< (const iterator& l, const iterator& r) - { return l.pn->up < r.pn->up; } + friend bool operator< (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up < r.m_pn->up; } - friend bool operator<= (const iterator& l, const iterator& r) - { return l.pn->up <= r.pn->up; } + friend bool operator<= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up <= r.m_pn->up; } - friend bool operator> (const iterator& l, const iterator& r) - { return l.pn->up > r.pn->up; } + friend bool operator> (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up > r.m_pn->up; } - friend bool operator>= (const iterator& l, const iterator& r) - { return l.pn->up >= r.pn->up; } - - node_ptr pn; + friend bool operator>= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + { return l.m_pn->up >= r.m_pn->up; } }; template @@ -354,7 +359,6 @@ struct index_traits } } - #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING static bool invariants(index_type &index) { @@ -431,8 +435,10 @@ class stable_vector { ///@cond typedef allocator_traits allocator_traits_type; - typedef typename boost::intrusive::pointer_traits - :: + typedef boost::intrusive:: + pointer_traits + ptr_traits; + typedef typename ptr_traits:: template rebind_pointer::type void_ptr; typedef typename allocator_traits_type:: template portable_rebind_alloc @@ -451,10 +457,8 @@ class stable_vector typedef typename index_traits_type::index_iterator index_iterator; typedef typename index_traits_type:: const_index_iterator const_index_iterator; - typedef boost::intrusive:: - pointer_traits - ptr_traits; - typedef stable_vector_detail::node node_type; + typedef stable_vector_detail::node + node_type; typedef typename ptr_traits::template rebind_pointer::type node_ptr; typedef boost::intrusive:: @@ -495,13 +499,11 @@ class stable_vector friend class stable_vector_detail::clear_on_destroy; typedef stable_vector_detail::iterator - < T - , typename allocator_traits::reference - , typename allocator_traits::pointer> iterator_impl; + < typename allocator_traits::pointer + , false> iterator_impl; typedef stable_vector_detail::iterator - < T - , typename allocator_traits::const_reference - , typename allocator_traits::const_pointer> const_iterator_impl; + < typename allocator_traits::pointer + , false> const_iterator_impl; ///@endcond public: diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp index fb97b7f..4a8cce4 100644 --- a/include/boost/container/static_vector.hpp +++ b/include/boost/container/static_vector.hpp @@ -81,8 +81,11 @@ class static_storage_allocator * possible. * * @par Error Handling - * Insertion beyond the capacity and out of bounds errors results in calling throw_bad_alloc(). - * The reason for this is because unlike vectors, static_vector does not perform allocation. + * Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or + * calling throw_bad_alloc() if not enabled. + * + * std::out_of_range is thrown if out of bound access is performed in `at()` if exceptions are + * enabled, throw_out_of_range() if not enabled. * * @tparam Value The type of element that will be stored. * @tparam Capacity The maximum number of elements static_vector can store, fixed at compile time. diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index dac536a..db41b60 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -61,20 +61,27 @@ namespace container_detail { #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER -//! Const vector_iterator used to iterate through a vector. -template -class vector_const_iterator +template +class vec_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef typename boost::intrusive::pointer_traits::element_type value_type; typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef typename boost::intrusive::pointer_traits::template - rebind_pointer::type pointer; - typedef const value_type& reference; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; /// @cond - protected: + private: Pointer m_ptr; public: @@ -84,7 +91,7 @@ class vector_const_iterator Pointer &get_ptr() BOOST_CONTAINER_NOEXCEPT { return m_ptr; } - explicit vector_const_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT + explicit vec_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT : m_ptr(ptr) {} /// @endcond @@ -92,7 +99,7 @@ class vector_const_iterator public: //Constructors - vector_const_iterator() BOOST_CONTAINER_NOEXCEPT + vec_iterator() BOOST_CONTAINER_NOEXCEPT #ifndef NDEBUG : m_ptr() #else @@ -100,139 +107,80 @@ class vector_const_iterator #endif {} + vec_iterator(vec_iterator const& other) BOOST_CONTAINER_NOEXCEPT + : m_ptr(other.get_ptr()) + {} + //Pointer like operators reference operator*() const BOOST_CONTAINER_NOEXCEPT { return *m_ptr; } - const value_type * operator->() const BOOST_CONTAINER_NOEXCEPT - { return container_detail::to_raw_pointer(m_ptr); } + pointer operator->() const BOOST_CONTAINER_NOEXCEPT + { return ::boost::intrusive::pointer_traits::pointer_to(this->operator*()); } reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT { return m_ptr[off]; } //Increment / Decrement - vector_const_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator++() BOOST_CONTAINER_NOEXCEPT { ++m_ptr; return *this; } - vector_const_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(m_ptr++); } + vec_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(m_ptr++); } - vector_const_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator--() BOOST_CONTAINER_NOEXCEPT { --m_ptr; return *this; } - vector_const_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(m_ptr--); } + vec_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(m_ptr--); } //Arithmetic - vector_const_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT { m_ptr += off; return *this; } - vector_const_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT { m_ptr -= off; return *this; } - friend vector_const_iterator operator+(const vector_const_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT - { return vector_const_iterator(x.m_ptr+off); } + friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT + { return vec_iterator(x.m_ptr+off); } - friend vector_const_iterator operator+(difference_type off, vector_const_iterator right) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_CONTAINER_NOEXCEPT { right.m_ptr += off; return right; } - friend vector_const_iterator operator-(vector_const_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT { left.m_ptr -= off; return left; } - friend difference_type operator-(const vector_const_iterator &left, const vector_const_iterator& right) BOOST_CONTAINER_NOEXCEPT + friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_CONTAINER_NOEXCEPT { return left.m_ptr - right.m_ptr; } //Comparison operators - friend bool operator== (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr == r.m_ptr; } - friend bool operator!= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr != r.m_ptr; } - friend bool operator< (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr < r.m_ptr; } - friend bool operator<= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr <= r.m_ptr; } - friend bool operator> (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr > r.m_ptr; } - friend bool operator>= (const vector_const_iterator& l, const vector_const_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT { return l.m_ptr >= r.m_ptr; } }; -//! Iterator used to iterate through a vector -template -class vector_iterator - : public vector_const_iterator -{ - typedef vector_const_iterator base_t; - public: - explicit vector_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT - : base_t(ptr) - {} - - public: - typedef std::random_access_iterator_tag iterator_category; - typedef typename boost::intrusive::pointer_traits::element_type value_type; - typedef typename boost::intrusive::pointer_traits::difference_type difference_type; - typedef Pointer pointer; - typedef value_type& reference; - - //Constructors - vector_iterator() BOOST_CONTAINER_NOEXCEPT - : base_t() - {} - - //Pointer like operators - reference operator*() const BOOST_CONTAINER_NOEXCEPT - { return *this->m_ptr; } - - value_type* operator->() const BOOST_CONTAINER_NOEXCEPT - { return container_detail::to_raw_pointer(this->m_ptr); } - - reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT - { return this->m_ptr[off]; } - - //Increment / Decrement - vector_iterator& operator++() BOOST_CONTAINER_NOEXCEPT - { ++this->m_ptr; return *this; } - - vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT - { return vector_iterator(this->m_ptr++); } - - vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT - { --this->m_ptr; return *this; } - - vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT - { return vector_iterator(this->m_ptr--); } - - // Arithmetic - vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT - { this->m_ptr += off; return *this; } - - vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT - { this->m_ptr -= off; return *this; } - - friend vector_iterator operator+(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT - { left.m_ptr += off; return left; } - - friend vector_iterator operator+(difference_type off, vector_iterator right) BOOST_CONTAINER_NOEXCEPT - { right.m_ptr += off; return right; } - - friend vector_iterator operator-(vector_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT - { left.m_ptr -= off; return left; } -}; - } //namespace container_detail { -template -const Pointer &vector_iterator_get_ptr(const container_detail::vector_const_iterator &it) BOOST_CONTAINER_NOEXCEPT +template +const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator &it) BOOST_CONTAINER_NOEXCEPT { return it.get_ptr(); } -template -Pointer &get_ptr(container_detail::vector_const_iterator &it) BOOST_CONTAINER_NOEXCEPT +template +Pointer &get_ptr(container_detail::vec_iterator &it) BOOST_CONTAINER_NOEXCEPT { return it.get_ptr(); } namespace container_detail { @@ -251,7 +199,7 @@ struct vector_get_ptr_pointer_to_non_const typedef typename pointer_traits_t ::template rebind_pointer::type return_type; - static return_type get_ptr(const const_pointer &ptr) + static return_type get_ptr(const const_pointer &ptr) BOOST_CONTAINER_NOEXCEPT { return boost::intrusive::pointer_traits::const_cast_from(ptr); } }; @@ -259,7 +207,7 @@ template struct vector_get_ptr_pointer_to_non_const { typedef const Pointer & return_type; - static return_type get_ptr(const Pointer &ptr) + static return_type get_ptr(const Pointer &ptr) BOOST_CONTAINER_NOEXCEPT { return ptr; } }; @@ -565,6 +513,7 @@ struct vector_alloc_holder::value > alloc_version; - boost::container::container_detail::vector_alloc_holder m_holder; - typedef container_detail::vector_alloc_holder base_t; - typedef allocator_traits allocator_traits_type; + boost::container::container_detail::vector_alloc_holder + m_holder; + typedef allocator_traits allocator_traits_type; template friend class vector; + + typedef typename ::boost::container::allocator_traits + ::pointer pointer_impl; + typedef container_detail::vec_iterator iterator_impl; + typedef container_detail::vec_iterator const_iterator_impl; + /// @endcond public: ////////////////////////////////////////////// @@ -611,8 +566,8 @@ class vector typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; #else - typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_iterator) iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_const_iterator) const_iterator; + typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; #endif typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp index 092846f..d2cd6b6 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -48,8 +48,6 @@ bool CheckEqualContainers(const MyBoostCont *boostcont, const MyStdCont *stdcont if(boostcont->size() != stdcont->size()) return false; - typedef typename MyBoostCont::value_type value_type; - typename MyBoostCont::const_iterator itboost(boostcont->begin()), itboostend(boostcont->end()); typename MyStdCont::const_iterator itstd(stdcont->begin()); typename MyStdCont::size_type dist = (typename MyStdCont::size_type)std::distance(itboost, itboostend); diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 5854b59..146285c 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -475,6 +475,13 @@ int main() { using namespace boost::container::test; + //Allocator argument container + { + flat_set set_((std::allocator())); + flat_multiset multiset_((std::allocator())); + flat_map map_((std::allocator >())); + flat_multimap multimap_((std::allocator >())); + } //Now test move semantics { test_move >(); diff --git a/test/list_test.cpp b/test/list_test.cpp index fca017f..c7198e7 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -34,10 +34,10 @@ template class boost::container::list >::container_type::iterator >; -template class list_iterator - >::container_type::iterator>; +template class iterator + >::container_type::iterator, true >; +template class iterator + >::container_type::iterator, false>; } diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 808d25c..785bcc2 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -31,15 +31,6 @@ template class boost::container::slist >; -namespace container_detail { - -template class slist_const_iterator - >::container_type::iterator >; -template class slist_iterator - >::container_type::iterator>; - -} - }} typedef slist MyList; diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index 748886e..459aace 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -41,10 +41,10 @@ template class stable_vector; -template class iterator< int, const int &, const int *>; +template class iterator; +template class iterator; -} +} //namespace stable_vector_detail{ }} diff --git a/test/tree_test.cpp b/test/tree_test.cpp index dca5a31..60d593f 100644 --- a/test/tree_test.cpp +++ b/test/tree_test.cpp @@ -247,6 +247,13 @@ int main () map map_; multimap multimap_; } + //Allocator argument container + { + set set_((std::allocator())); + multiset multiset_((std::allocator())); + map map_((std::allocator >())); + multimap multimap_((std::allocator >())); + } //Now test move semantics { test_move >(); @@ -255,7 +262,6 @@ int main () test_move >(); } - //using namespace boost::container::detail; if(0 != test::set_test; -template class vector_iterator; +template class vec_iterator; +template class vec_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER