Merged revision(s) 84341-85442 from trunk/boost/container. Merged revision(s) 84342-85442 from trunk/libs/container. First Container merge for 1.55

[SVN r85443]
This commit is contained in:
Ion Gaztañaga
2013-08-24 10:41:09 +00:00
parent e7b1fde968
commit f1468db73f
24 changed files with 741 additions and 842 deletions

View File

@@ -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<allocator_type>::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)
@@ -581,22 +623,6 @@ If you need a memory optimized version of `boost::container::vector<bool>` 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

View File

@@ -75,11 +75,10 @@ template <class T, class Allocator>
#endif
class deque;
template <class T, class Allocator>
template <class T>
struct deque_value_traits
{
typedef T value_type;
typedef Allocator allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
static const bool trivial_copy = has_trivial_copy<value_type>::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<class T>
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 Pointer, bool IsConst>
class deque_iterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename if_c
< IsConst
, typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::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_type>::value; }
typedef Pointer val_alloc_ptr;
typedef typename boost::intrusive::pointer_traits<Pointer>::
template rebind_pointer<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<Pointer, false> 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<Pointer, false> unconst() const BOOST_CONTAINER_NOEXCEPT
{
return deque_iterator<Pointer, false>(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 <class T, class Allocator>
template <class Allocator>
class deque_base
{
BOOST_COPYABLE_AND_MOVABLE(deque_base)
@@ -124,257 +321,26 @@ class deque_base
protected:
typedef deque_value_traits<T, Allocator> traits_t;
typedef deque_value_traits<val_alloc_val> 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<val_alloc_val>::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<std::random_access_iterator_tag,
val_alloc_val, val_alloc_diff,
val_alloc_cptr, val_alloc_cref>
{
public:
static size_type s_buffer_size() { return deque_base<T, Allocator>::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<T, Allocator>;
friend class deque_base<T, Allocator>;
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<T, Allocator>;
friend class deque_base<T, Allocator>;
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<const const_iterator &>(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<const const_iterator&>(*this) - right; }
};
typedef container_detail::deque_iterator<val_alloc_ptr, false> iterator;
typedef container_detail::deque_iterator<val_alloc_ptr, true > 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 <class T, class Allocator = std::allocator<T> >
#else
template <class T, class Allocator>
#endif
class deque : protected deque_base<T, Allocator>
class deque : protected deque_base<Allocator>
{
/// @cond
private:
typedef deque_base<T, Allocator> Base;
typedef deque_base<Allocator> Base;
/// @endcond
public:
@@ -1397,7 +1363,7 @@ class deque : protected deque_base<T, Allocator>
)
{
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<T, Allocator>
//! 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<T, Allocator>
const size_type n = static_cast<size_type>(last - first);
const size_type elems_before = static_cast<size_type>(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<T, Allocator>
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<T, Allocator>
template<class InsertProxy>
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<T, Allocator>
}
// 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<T, Allocator>
// 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<T, Allocator>
// Nonmember functions.
template <class T, class Allocator>
inline bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{
return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
}
template <class T, class Allocator>
inline bool operator<(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator<(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{
return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class T, class Allocator>
inline bool operator!=(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator!=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(x == y); }
template <class T, class Allocator>
inline bool operator>(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator>(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return y < x; }
template <class T, class Allocator>
inline bool operator>=(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator>=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(x < y); }
template <class T, class Allocator>
inline bool operator<=(const deque<T, Allocator>& x, const deque<T, Allocator>& y)
inline bool operator<=(const deque<T, Allocator>& x, const deque<T, Allocator>& y) BOOST_CONTAINER_NOEXCEPT
{ return !(y < x); }
template <class T, class Allocator>

View File

@@ -85,9 +85,9 @@ struct get_flat_tree_iterators
rebind_pointer<const iterator_element_type>::type const_iterator;
#else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef typename container_detail::
vector_iterator<Pointer> iterator;
vec_iterator<Pointer, false> iterator;
typedef typename container_detail::
vector_const_iterator<Pointer> const_iterator;
vec_iterator<Pointer, true > const_iterator;
#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_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<const value_compare&>(d)), m_vect(d.m_vect)
{}
@@ -131,15 +131,18 @@ class flat_tree
: value_compare(boost::move(static_cast<value_compare&>(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)
{ }

View File

@@ -23,6 +23,7 @@
#include <boost/move/utility.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/static_assert.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
@@ -585,24 +586,112 @@ struct is_bidirectional_iterator<T, false>
static const bool value = false;
};
template<class T, class IIterator>
template<class IIterator>
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<IIterator>::pointer it_pointer;
typedef typename std::iterator_traits<IIterator>::difference_type difference_type;
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
template rebind_pointer<T>::type pointer;
template rebind_pointer<value_type>::type pointer;
typedef typename ::boost::intrusive::pointer_traits<it_pointer>::
template rebind_pointer<const T>::type const_pointer;
template rebind_pointer<const value_type>::type const_pointer;
typedef typename ::boost::intrusive::
pointer_traits<pointer>::reference reference;
typedef typename ::boost::intrusive::
pointer_traits<const_pointer>::reference const_reference;
typedef typename IIterator::iterator_category iterator_category;
};
template<class IIterator, bool IsConst>
struct std_iterator
{
typedef typename std::iterator
< typename iiterator_types<IIterator>::iterator_category
, typename iiterator_types<IIterator>::value_type
, typename iiterator_types<IIterator>::difference_type
, typename iiterator_types<IIterator>::const_pointer
, typename iiterator_types<IIterator>::const_reference> type;
};
template<class IIterator>
struct std_iterator<IIterator, false>
{
typedef typename std::iterator
< typename iiterator_types<IIterator>::iterator_category
, typename iiterator_types<IIterator>::value_type
, typename iiterator_types<IIterator>::difference_type
, typename iiterator_types<IIterator>::pointer
, typename iiterator_types<IIterator>::reference> type;
};
template<class IIterator, bool IsConst>
class iterator
: public std_iterator<IIterator, IsConst>::type
{
typedef typename std_iterator<IIterator, IsConst>::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<IIterator, false> 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<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>::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 {

View File

@@ -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<ValueCompare &>(*this); }
@@ -67,11 +71,10 @@ struct node_compare
{ return ValueCompare::operator()(a.get_data(), b.get_data()); }
};
template<class A, class ICont, class Pred = container_detail::nat>
template<class A, class ICont, class ValPred = container_detail::nat>
struct node_alloc_holder
{
typedef allocator_traits<A> allocator_traits_type;
typedef node_alloc_holder<A, ICont> 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<class ConvertibleToAlloc>
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c)
members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const ValPred &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(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))
{}

View File

@@ -20,8 +20,8 @@
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/intrusive/rbtree.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/container/detail/destroyers.hpp>
@@ -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
<A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
>::type
, KeyCompare
, tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
>
{
typedef tree_value_compare
<Key, Value, KeyCompare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_rbtree_type
< A, tree_value_compare
<Key, Value, KeyCompare, KeyOfValue>
>::type Icont;
< A, ValComp>::type Icont;
typedef container_detail::node_alloc_holder
<A, Icont, KeyCompare> AllocHolder;
<A, Icont, ValComp> 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<A>::pointer pointer;
typedef typename boost::container::
@@ -373,109 +376,21 @@ class rbtree
typedef key_node_compare<value_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 <Key, Value, KeyOfValue, KeyCompare, A>;
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 <Key, Value, KeyOfValue, KeyCompare, A>;
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>::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<iiterator, false> iterator;
typedef container_detail::iterator<iiterator, true > const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_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 <class InputIterator>
@@ -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<AllocHolder&>(x)), x.key_comp())
: AllocHolder(::boost::move(static_cast<AllocHolder&>(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());

View File

@@ -12,6 +12,7 @@
#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
#include "config_begin.hpp"
#include "workaround.hpp"
#include <cstdio>
#include <cstring> //for ::memcpy
#include <boost/type_traits/is_fundamental.hpp>
@@ -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);

View File

@@ -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

View File

@@ -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 Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
@@ -173,7 +175,15 @@ class flat_map
//!
//! <b>Complexity</b>: Constant.
explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) {}
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_map(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: 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<Key,T,Compare,Allocator>& x,
//!
//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<Key, T> ></i>).
//!
//! 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 Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
@@ -1024,7 +1043,15 @@ class flat_multimap
//! <b>Complexity</b>: Constant.
explicit flat_multimap(const Compare& comp,
const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) { }
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_multimap(const allocator_type& a)
: m_flat_tree(container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).

View File

@@ -51,9 +51,7 @@ inline bool operator<(const flat_set<Key,Compare,Allocator>& 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<Key,Compare,Allocator>& 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 Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
@@ -121,6 +121,13 @@ class flat_set
: m_flat_tree(comp, a)
{}
//! <b>Effects</b>: Constructs an empty flat_set using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_set(const allocator_type& a)
: m_flat_tree(a)
{}
//! <b>Effects</b>: 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<Key,Compare,Allocator>& 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 Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
@@ -810,9 +818,21 @@ class flat_multiset
: m_flat_tree()
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified
//! comparison object and allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_multiset(const Compare& comp,
const allocator_type& a = allocator_type())
: m_flat_tree(comp, a) {}
: m_flat_tree(comp, a)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit flat_multiset(const allocator_type& a)
: m_flat_tree(a)
{}
template <class InputIterator>
flat_multiset(InputIterator first, InputIterator last,

View File

@@ -18,6 +18,8 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/move/utility.hpp>
#include <boost/move/iterator.hpp>
@@ -26,7 +28,6 @@
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/assert.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
@@ -64,8 +65,16 @@ struct list_node
list_node();
public:
typedef T value_type;
typedef typename list_hook<VoidPointer>::type hook_type;
T m_data;
T &get_data()
{ return this->m_data; }
const T &get_data() const
{ return this->m_data; }
};
template<class Allocator>
@@ -89,105 +98,6 @@ struct intrusive_list_type
typedef container_type type ;
};
template<class T, class IIterator>
class list_const_iterator
: public std::iterator< std::bidirectional_iterator_tag, T
, typename iiterator_types<T, IIterator>::difference_type
, typename iiterator_types<T, IIterator>::const_pointer
, typename iiterator_types<T, IIterator>::const_reference>
{
protected:
IIterator m_it;
public:
typedef typename iiterator_types<T, IIterator>::const_pointer const_pointer;
typedef typename iiterator_types<T, IIterator>::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<const_pointer>::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 T, class IIterator>
class list_iterator
: public list_const_iterator<T, IIterator>
{
private:
typedef list_const_iterator<T, IIterator> const_iterator;
public:
typedef typename iiterator_types<T, IIterator>::pointer pointer;
typedef typename iiterator_types<T, IIterator>::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>::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<T, typename Icont::iterator> iterator_impl;
typedef container_detail::list_const_iterator<T, typename Icont::iterator>const_iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, true> 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>::iterator_category ItCat;
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}

View File

@@ -138,6 +138,16 @@ class map
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty map using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit map(const allocator_type& a)
: m_tree(a)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: 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<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison
//! object and allocator.
//! <b>Effects</b>: Constructs an empty multimap using the specified allocator.
//!
//! <b>Complexity</b>: 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<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison
//! object and allocator.
//!
//! <b>Complexity</b>: Constant.
explicit multimap(const allocator_type& a)
: m_tree(a)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).
//!

View File

@@ -113,6 +113,13 @@ class set
: m_tree(comp, a)
{}
//! <b>Effects</b>: Constructs an empty set using the specified allocator object.
//!
//! <b>Complexity</b>: Constant.
explicit set(const allocator_type& a)
: m_tree(a)
{}
//! <b>Effects</b>: 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)
{}
//! <b>Effects</b>: Constructs an empty multiset using the specified allocator.
//!
//! <b>Complexity</b>: Constant.
explicit multiset(const allocator_type& a)
: m_tree(a)
{}
//! <b>Effects</b>: Constructs an empty multiset using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).
//!

View File

@@ -24,6 +24,7 @@
#include <boost/move/detail/move_helpers.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
@@ -69,8 +70,16 @@ struct slist_node
slist_node();
public:
typedef T value_type;
typedef typename slist_hook<VoidPointer>::type hook_type;
T m_data;
T &get_data()
{ return this->m_data; }
const T &get_data() const
{ return this->m_data; }
};
template<class Allocator>
@@ -95,93 +104,6 @@ struct intrusive_slist_type
typedef container_type type ;
};
template<class T, class IIterator>
class slist_const_iterator
: public std::iterator< std::forward_iterator_tag, T
, typename iiterator_types<T, IIterator>::difference_type
, typename iiterator_types<T, IIterator>::const_pointer
, typename iiterator_types<T, IIterator>::const_reference>
{
protected:
IIterator m_it;
public:
typedef typename iiterator_types<T, IIterator>::const_pointer const_pointer;
typedef typename iiterator_types<T, IIterator>::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<const_pointer>::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 T, class IIterator>
class slist_iterator
: public slist_const_iterator<T, IIterator>
{
private:
typedef slist_const_iterator<T, IIterator> const_iterator;
public:
typedef typename iiterator_types<T, IIterator>::pointer pointer;
typedef typename iiterator_types<T, IIterator>::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>::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<T, typename Icont::iterator> iterator_impl;
typedef container_detail::slist_const_iterator<T, typename Icont::iterator>const_iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
typedef container_detail::iterator<typename Icont::iterator, true > 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>::iterator_category ItCat;
this->assign( boost::make_move_iterator(x.begin())
, boost::make_move_iterator(x.end()));
}

View File

@@ -88,7 +88,7 @@ class clear_on_destroy
bool do_clear_;
};
template<typename VoidPointer, typename T>
template<typename Pointer>
struct node;
template<class VoidPtr>
@@ -116,167 +116,172 @@ struct node_base
node_base_ptr_ptr up;
};
template<typename VoidPointer, typename T>
template<typename Pointer>
struct node
: public node_base<VoidPointer>
: public node_base
<typename ::boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<void>::type
>
{
private:
node();
public:
T value;
typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
};
template<typename T, typename Reference, typename Pointer>
template<typename Pointer, bool IsConst>
class iterator
: public std::iterator< std::random_access_iterator_tag
, T
, typename boost::intrusive::
pointer_traits<Pointer>::difference_type
, Pointer
, Reference>
{
typedef boost::intrusive::
pointer_traits<Pointer> ptr_traits;
typedef typename ptr_traits::template
typedef boost::intrusive::pointer_traits<Pointer> 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<const value_type>::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<void>::type void_ptr;
typedef node<void_ptr, T> node_type;
typedef node<Pointer> node_type;
typedef node_base<void_ptr> node_base_type;
typedef typename ptr_traits::template
typedef typename non_const_ptr_traits::template
rebind_pointer<node_type>::type node_ptr;
typedef boost::intrusive::
pointer_traits<node_ptr> node_ptr_traits;
typedef typename ptr_traits::template
typedef typename non_const_ptr_traits::template
rebind_pointer<node_base_type>::type node_base_ptr;
typedef typename ptr_traits::template
typedef typename non_const_ptr_traits::template
rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
typedef typename ptr_traits::template
rebind_pointer<T>::type friend_iterator_pointer;
friend class iterator<T, const T, friend_iterator_pointer>;
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<T, T&, friend_iterator_pointer>& x)
: pn(x.pn)
iterator(iterator<Pointer, false> 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<pointer> 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<class VoidPtr, class VoidAllocator>
@@ -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> allocator_traits_type;
typedef typename boost::intrusive::pointer_traits
<typename allocator_traits_type::pointer>::
typedef boost::intrusive::
pointer_traits
<typename allocator_traits_type::pointer> ptr_traits;
typedef typename ptr_traits::
template rebind_pointer<void>::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
<typename allocator_traits_type::pointer> ptr_traits;
typedef stable_vector_detail::node<void_ptr, T> node_type;
typedef stable_vector_detail::node
<typename ptr_traits::pointer> node_type;
typedef typename ptr_traits::template
rebind_pointer<node_type>::type node_ptr;
typedef boost::intrusive::
@@ -495,13 +499,11 @@ class stable_vector
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
typedef stable_vector_detail::iterator
< T
, typename allocator_traits<Allocator>::reference
, typename allocator_traits<Allocator>::pointer> iterator_impl;
< typename allocator_traits<Allocator>::pointer
, false> iterator_impl;
typedef stable_vector_detail::iterator
< T
, typename allocator_traits<Allocator>::const_reference
, typename allocator_traits<Allocator>::const_pointer> const_iterator_impl;
< typename allocator_traits<Allocator>::pointer
, false> const_iterator_impl;
///@endcond
public:

View File

@@ -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.

View File

@@ -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 Pointer>
class vector_const_iterator
template <class Pointer, bool IsConst>
class vec_iterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::type pointer;
typedef const value_type& reference;
typedef typename if_c
< IsConst
, typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::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<Pointer, false> 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>::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 Pointer>
class vector_iterator
: public vector_const_iterator<Pointer>
{
typedef vector_const_iterator<Pointer> 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<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::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<class Pointer>
const Pointer &vector_iterator_get_ptr(const container_detail::vector_const_iterator<Pointer> &it) BOOST_CONTAINER_NOEXCEPT
template<class Pointer, bool IsConst>
const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_CONTAINER_NOEXCEPT
{ return it.get_ptr(); }
template<class Pointer>
Pointer &get_ptr(container_detail::vector_const_iterator<Pointer> &it) BOOST_CONTAINER_NOEXCEPT
template<class Pointer, bool IsConst>
Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &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<non_const_element_type>::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<return_type>::const_cast_from(ptr); }
};
@@ -259,7 +207,7 @@ template<class Pointer>
struct vector_get_ptr_pointer_to_non_const<Pointer, false>
{
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<Allocator, container_detail::integral_constant<unsign
};
} //namespace container_detail {
/// @endcond
//! \class vector
@@ -585,11 +534,17 @@ class vector
typedef container_detail::integral_constant
<unsigned, boost::container::container_detail::version
<Allocator>::value > alloc_version;
boost::container::container_detail::vector_alloc_holder<Allocator, alloc_version> m_holder;
typedef container_detail::vector_alloc_holder<Allocator> base_t;
boost::container::container_detail::vector_alloc_holder
<Allocator, alloc_version> m_holder;
typedef allocator_traits<Allocator> allocator_traits_type;
template <class U, class UAllocator>
friend class vector;
typedef typename ::boost::container::allocator_traits
<Allocator>::pointer pointer_impl;
typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl;
typedef container_detail::vec_iterator<pointer_impl, true > 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<pointer>) iterator;
typedef BOOST_CONTAINER_IMPDEF(container_detail::vector_const_iterator<pointer>) 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<iterator>) reverse_iterator;
typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator<const_iterator>) const_reverse_iterator;

View File

@@ -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);

View File

@@ -475,6 +475,13 @@ int main()
{
using namespace boost::container::test;
//Allocator argument container
{
flat_set<int> set_((std::allocator<int>()));
flat_multiset<int> multiset_((std::allocator<int>()));
flat_map<int, int> map_((std::allocator<std::pair<int, int> >()));
flat_multimap<int, int> multimap_((std::allocator<std::pair<int, int> >()));
}
//Now test move semantics
{
test_move<flat_set<recursive_flat_set> >();

View File

@@ -34,10 +34,10 @@ template class boost::container::list<test::movable_and_copyable_int,
namespace container_detail {
template class list_const_iterator
<int, intrusive_list_type< std::allocator<int> >::container_type::iterator >;
template class list_iterator
<int, intrusive_list_type< std::allocator<int> >::container_type::iterator>;
template class iterator
<intrusive_list_type< std::allocator<int> >::container_type::iterator, true >;
template class iterator
<intrusive_list_type< std::allocator<int> >::container_type::iterator, false>;
}

View File

@@ -31,15 +31,6 @@ template class boost::container::slist<test::movable_and_copyable_int,
template class boost::container::slist<test::movable_and_copyable_int,
std::allocator<test::movable_and_copyable_int> >;
namespace container_detail {
template class slist_const_iterator
<int, intrusive_slist_type< std::allocator<int> >::container_type::iterator >;
template class slist_iterator
<int, intrusive_slist_type< std::allocator<int> >::container_type::iterator>;
}
}}
typedef slist<int> MyList;

View File

@@ -41,10 +41,10 @@ template class stable_vector<test::movable_and_copyable_int,
namespace stable_vector_detail{
template class iterator< int, int &, int *>;
template class iterator< int, const int &, const int *>;
template class iterator<int*, false>;
template class iterator<int*, true >;
}
} //namespace stable_vector_detail{
}}

View File

@@ -247,6 +247,13 @@ int main ()
map<recursive_map, recursive_map> map_;
multimap<recursive_multimap, recursive_multimap> multimap_;
}
//Allocator argument container
{
set<int> set_((std::allocator<int>()));
multiset<int> multiset_((std::allocator<int>()));
map<int, int> map_((std::allocator<std::pair<const int, int> >()));
multimap<int, int> multimap_((std::allocator<std::pair<const int, int> >()));
}
//Now test move semantics
{
test_move<set<recursive_set> >();
@@ -255,7 +262,6 @@ int main ()
test_move<multimap<recursive_multimap, recursive_multimap> >();
}
//using namespace boost::container::detail;
if(0 != test::set_test<MyBoostSet
,MyStdSet

View File

@@ -43,8 +43,8 @@ namespace container_detail {
#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
template class vector_const_iterator<int*>;
template class vector_iterator<int*>;
template class vec_iterator<int*, true >;
template class vec_iterator<int*, false>;
#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER