|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r49276 - in trunk/boost: interprocess interprocess/allocators interprocess/allocators/detail interprocess/containers interprocess/containers/detail interprocess/detail interprocess/ipc interprocess/mem_algo interprocess/mem_algo/detail interprocess/smart_ptr interprocess/sync interprocess/sync/emulation interprocess/sync/posix intrusive intrusive/detail
From: igaztanaga_at_[hidden]
Date: 2008-10-11 09:15:00
Author: igaztanaga
Date: 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
New Revision: 49276
URL: http://svn.boost.org/trac/boost/changeset/49276
Log:
Changes and fixes for Boost 1.37
Added:
trunk/boost/interprocess/detail/advanced_insert_int.hpp (contents, props changed)
trunk/boost/interprocess/detail/preprocessor.hpp (contents, props changed)
trunk/boost/interprocess/detail/variadic_templates_tools.hpp (contents, props changed)
trunk/boost/intrusive/detail/workaround.hpp (contents, props changed)
Text files modified:
trunk/boost/interprocess/allocators/allocator.hpp | 2
trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp | 21
trunk/boost/interprocess/allocators/detail/node_pool.hpp | 15
trunk/boost/interprocess/anonymous_shared_memory.hpp | 12
trunk/boost/interprocess/containers/deque.hpp | 958 ++++++++++++++++++---------------------
trunk/boost/interprocess/containers/detail/flat_tree.hpp | 204 +++++++-
trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp | 98 ++-
trunk/boost/interprocess/containers/detail/tree.hpp | 300 +++++++++--
trunk/boost/interprocess/containers/flat_map.hpp | 281 +++++++++--
trunk/boost/interprocess/containers/flat_set.hpp | 187 +++++++
trunk/boost/interprocess/containers/list.hpp | 252 ++++++++--
trunk/boost/interprocess/containers/map.hpp | 102 ++++
trunk/boost/interprocess/containers/set.hpp | 167 ++++++
trunk/boost/interprocess/containers/slist.hpp | 263 ++++++++--
trunk/boost/interprocess/containers/string.hpp | 2
trunk/boost/interprocess/containers/vector.hpp | 782 +++++++++++++++++++-------------
trunk/boost/interprocess/detail/algorithms.hpp | 11
trunk/boost/interprocess/detail/atomic.hpp | 8
trunk/boost/interprocess/detail/config_begin.hpp | 4
trunk/boost/interprocess/detail/intersegment_ptr.hpp | 69 +-
trunk/boost/interprocess/detail/managed_memory_impl.hpp | 10
trunk/boost/interprocess/detail/managed_multi_shared_memory.hpp | 4
trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp | 8
trunk/boost/interprocess/detail/move.hpp | 12
trunk/boost/interprocess/detail/named_proxy.hpp | 193 +++++--
trunk/boost/interprocess/detail/os_file_functions.hpp | 13
trunk/boost/interprocess/detail/segment_manager_helper.hpp | 30
trunk/boost/interprocess/detail/type_traits.hpp | 41 -
trunk/boost/interprocess/detail/utilities.hpp | 151 ++++-
trunk/boost/interprocess/detail/win32_api.hpp | 17
trunk/boost/interprocess/errors.hpp | 2
trunk/boost/interprocess/file_mapping.hpp | 2
trunk/boost/interprocess/interprocess_fwd.hpp | 5
trunk/boost/interprocess/ipc/message_queue.hpp | 36 +
trunk/boost/interprocess/mapped_region.hpp | 11
trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp | 37
trunk/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp | 72 +-
trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp | 75 +-
trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp | 85 +-
trunk/boost/interprocess/offset_ptr.hpp | 16
trunk/boost/interprocess/segment_manager.hpp | 88 +-
trunk/boost/interprocess/shared_memory_object.hpp | 1
trunk/boost/interprocess/smart_ptr/unique_ptr.hpp | 2
trunk/boost/interprocess/smart_ptr/weak_ptr.hpp | 2
trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp | 16
trunk/boost/interprocess/sync/emulation/interprocess_mutex.hpp | 10
trunk/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp | 4
trunk/boost/interprocess/sync/emulation/interprocess_semaphore.hpp | 4
trunk/boost/interprocess/sync/file_lock.hpp | 8
trunk/boost/interprocess/sync/interprocess_condition.hpp | 12
trunk/boost/interprocess/sync/interprocess_mutex.hpp | 2
trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp | 3
trunk/boost/interprocess/sync/interprocess_semaphore.hpp | 4
trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp | 12
trunk/boost/interprocess/sync/lock_options.hpp | 2
trunk/boost/interprocess/sync/named_condition.hpp | 16
trunk/boost/interprocess/sync/named_mutex.hpp | 16
trunk/boost/interprocess/sync/named_recursive_mutex.hpp | 8
trunk/boost/interprocess/sync/named_semaphore.hpp | 16
trunk/boost/interprocess/sync/named_upgradable_mutex.hpp | 26
trunk/boost/interprocess/sync/posix/interprocess_mutex.hpp | 4
trunk/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp | 4
trunk/boost/interprocess/sync/posix/interprocess_semaphore.hpp | 8
trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp | 2
trunk/boost/interprocess/sync/sharable_lock.hpp | 2
trunk/boost/interprocess/sync/upgradable_lock.hpp | 4
trunk/boost/intrusive/any_hook.hpp | 46 +
trunk/boost/intrusive/avl_set.hpp | 114 +++-
trunk/boost/intrusive/avl_set_hook.hpp | 42 +
trunk/boost/intrusive/avltree.hpp | 98 ++-
trunk/boost/intrusive/avltree_algorithms.hpp | 16
trunk/boost/intrusive/bs_set_hook.hpp | 62 +-
trunk/boost/intrusive/circular_slist_algorithms.hpp | 4
trunk/boost/intrusive/detail/assert.hpp | 18
trunk/boost/intrusive/detail/list_node.hpp | 3
trunk/boost/intrusive/detail/mpl.hpp | 172 ++++--
trunk/boost/intrusive/detail/slist_node.hpp | 3
trunk/boost/intrusive/detail/tree_algorithms.hpp | 4
trunk/boost/intrusive/hashtable.hpp | 892 +++++++++++++++++++++++++------------
trunk/boost/intrusive/intrusive_fwd.hpp | 152 +++++
trunk/boost/intrusive/linear_slist_algorithms.hpp | 4
trunk/boost/intrusive/list.hpp | 146 +++--
trunk/boost/intrusive/list_hook.hpp | 44 +
trunk/boost/intrusive/options.hpp | 214 ++++++++
trunk/boost/intrusive/pointer_plus_bits.hpp | 7
trunk/boost/intrusive/rbtree.hpp | 106 ++-
trunk/boost/intrusive/set.hpp | 116 +++-
trunk/boost/intrusive/set_hook.hpp | 44 +
trunk/boost/intrusive/sg_set.hpp | 116 +++-
trunk/boost/intrusive/sgtree.hpp | 96 ++-
trunk/boost/intrusive/sgtree_algorithms.hpp | 2
trunk/boost/intrusive/slist.hpp | 212 ++++----
trunk/boost/intrusive/slist_hook.hpp | 44 +
trunk/boost/intrusive/splay_set.hpp | 115 +++-
trunk/boost/intrusive/splay_set_hook.hpp | 44 +
trunk/boost/intrusive/splaytree.hpp | 109 ++-
trunk/boost/intrusive/splaytree_algorithms.hpp | 2
trunk/boost/intrusive/unordered_set.hpp | 154 +++++
trunk/boost/intrusive/unordered_set_hook.hpp | 44 +
99 files changed, 5442 insertions(+), 2637 deletions(-)
Modified: trunk/boost/interprocess/allocators/allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/allocator.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -147,7 +147,7 @@
(void)hint;
if(count > this->max_size())
throw bad_alloc();
- return pointer((value_type*)mp_mngr->allocate(count*sizeof(T)));
+ return pointer(static_cast<value_type*>(mp_mngr->allocate(count*sizeof(T))));
}
//!Deallocates memory previously allocated.
Modified: trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -410,14 +410,14 @@
(void)free_nodes;
assert(free_nodes == mp_impl->m_real_num_node);
assert(0 == to_deallocate->hdr_offset);
- hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block((block_info_t*)detail::get_pointer(to_deallocate));
+ hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(detail::get_pointer(to_deallocate));
mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder);
}
const private_adaptive_node_pool_impl *mp_impl;
};
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
- #define BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
+ //#define BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
void priv_invariants()
#ifdef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#undef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
@@ -463,10 +463,10 @@
for(; it != itend; ++it){
hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it);
for(std::size_t i = 0, max = m_num_subblocks; i < max; ++i){
- assert(hdr_off_holder->hdr_offset == std::size_t((char*)&*it- (char*)hdr_off_holder));
+ assert(hdr_off_holder->hdr_offset == std::size_t(reinterpret_cast<char*>(&*it)- reinterpret_cast<char*>(hdr_off_holder)));
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
- hdr_off_holder = (hdr_offset_holder *)((char*)hdr_off_holder + m_real_block_alignment);
+ hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
}
}
}
@@ -498,19 +498,20 @@
block_info_t *priv_block_from_node(void *node) const
{
hdr_offset_holder *hdr_off_holder =
- (hdr_offset_holder*)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
+ reinterpret_cast<hdr_offset_holder*>((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
- block_info_t *block = (block_info_t *)(((char*)hdr_off_holder) + hdr_off_holder->hdr_offset);
+ block_info_t *block = reinterpret_cast<block_info_t *>
+ (reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
assert(block->hdr_offset == 0);
return block;
}
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
{
- hdr_offset_holder *hdr_off_holder = (hdr_offset_holder*)
- (((char*)block) - (m_num_subblocks-1)*m_real_block_alignment);
- assert(hdr_off_holder->hdr_offset == std::size_t((char*)block - (char*)hdr_off_holder));
+ hdr_offset_holder *hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
+ (reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
+ assert(hdr_off_holder->hdr_offset == std::size_t(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
return hdr_off_holder;
@@ -526,7 +527,7 @@
for(std::size_t i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
- char *mem_address = detail::char_ptr_cast
+ char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
if(!mem_address) throw std::bad_alloc();
++m_totally_free_blocks;
Modified: trunk/boost/interprocess/allocators/detail/node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/node_pool.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -96,7 +96,7 @@
if (m_freelist.empty())
priv_alloc_block();
//We take the first free node
- node_t *n = (node_t*)&m_freelist.front();
+ node_t *n = &m_freelist.front();
m_freelist.pop_front();
++m_allocated;
return n;
@@ -292,13 +292,13 @@
: std::unary_function<typename free_nodes_t::value_type, bool>
{
is_between(const void *addr, std::size_t size)
- : beg_((const char *)addr), end_(beg_+size)
+ : beg_(static_cast<const char *>(addr)), end_(beg_+size)
{}
bool operator()(typename free_nodes_t::const_reference v) const
{
- return (beg_ <= (const char *)&v &&
- end_ > (const char *)&v);
+ return (beg_ <= reinterpret_cast<const char *>(&v) &&
+ end_ > reinterpret_cast<const char *>(&v));
}
private:
const char * beg_;
@@ -312,7 +312,7 @@
//element in the free Node list
std::size_t blocksize =
detail::get_rounded_size(m_real_node_size*m_nodes_per_block, alignment_of<node_t>::value);
- char *pNode = detail::char_ptr_cast
+ char *pNode = reinterpret_cast<char*>
(mp_segment_mngr_base->allocate(blocksize + sizeof(node_t)));
if(!pNode) throw bad_alloc();
char *pBlock = pNode;
@@ -337,14 +337,13 @@
//!Returns a reference to the block hook placed in the end of the block
static inline node_t & get_block_hook (void *block, std::size_t blocksize)
{
- return *static_cast<node_t*>(
- static_cast<void*>((detail::char_ptr_cast(block) + blocksize)));
+ return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
}
//!Returns the starting address of the block reference to the block hook placed in the end of the block
inline void *get_block_from_hook (node_t *hook, std::size_t blocksize)
{
- return static_cast<void*>((detail::char_ptr_cast(hook) - blocksize));
+ return (reinterpret_cast<char*>(hook) - blocksize);
}
private:
Modified: trunk/boost/interprocess/anonymous_shared_memory.hpp
==============================================================================
--- trunk/boost/interprocess/anonymous_shared_memory.hpp (original)
+++ trunk/boost/interprocess/anonymous_shared_memory.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -93,12 +93,12 @@
#endif
- address = mmap( (void*)address
- , size
- , PROT_READ|PROT_WRITE
- , flags
- , fd
- , 0);
+ address = mmap( address
+ , size
+ , PROT_READ|PROT_WRITE
+ , flags
+ , fd
+ , 0);
if(address == MAP_FAILED){
if(fd != -1)
Modified: trunk/boost/interprocess/containers/deque.hpp
==============================================================================
--- trunk/boost/interprocess/containers/deque.hpp (original)
+++ trunk/boost/interprocess/containers/deque.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -57,16 +57,21 @@
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
-#include <iterator>
#include <cstddef>
#include <iterator>
+#include <cassert>
#include <memory>
#include <algorithm>
#include <stdexcept>
#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/type_traits/has_nothrow_assign.hpp>
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/interprocess/detail/advanced_insert_int.hpp>
namespace boost {
namespace interprocess {
@@ -75,6 +80,21 @@
template <class T, class Alloc>
class deque;
+template <class T, class A>
+struct deque_value_traits
+{
+ typedef T value_type;
+ typedef A allocator_type;
+ static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
+ static const bool trivial_dctr_after_move =
+ has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
+ static const bool trivial_copy = has_trivial_copy<value_type>::value;
+ static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
+ static const bool trivial_assign = has_trivial_assign<value_type>::value;
+ static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
+
+};
+
// 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)
@@ -105,16 +125,18 @@
typedef allocator_type stored_allocator_type;
protected:
- enum { trivial_dctr_after_move = boost::has_trivial_destructor<val_alloc_val>::value };
+ typedef deque_value_traits<T, Alloc> traits_t;
typedef typename Alloc::template
rebind<typename Alloc::pointer>::other map_allocator_type;
+ static std::size_t s_buffer_size() { return deque_buf_size(sizeof(T)); }
+
val_alloc_ptr priv_allocate_node()
- { return this->alloc().allocate(deque_buf_size(sizeof(T))); }
+ { return this->alloc().allocate(s_buffer_size()); }
void priv_deallocate_node(val_alloc_ptr p)
- { this->alloc().deallocate(p, deque_buf_size(sizeof(T))); }
+ { this->alloc().deallocate(p, s_buffer_size()); }
ptr_alloc_ptr priv_allocate_map(std::size_t n)
{ return this->ptr_alloc().allocate(n); }
@@ -153,7 +175,7 @@
val_alloc_cptr, val_alloc_cref>
{
public:
- static std::size_t s_buffer_size() { return deque_buf_size(sizeof(T)); }
+ static std::size_t s_buffer_size() { return deque_base<T, Alloc>::s_buffer_size(); }
typedef std::random_access_iterator_tag iterator_category;
typedef val_alloc_val value_type;
@@ -297,7 +319,7 @@
public:
typedef std::random_access_iterator_tag iterator_category;
typedef val_alloc_val value_type;
- typedef ptr_alloc_ptr pointer;
+ typedef val_alloc_ptr pointer;
typedef val_alloc_ref reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
@@ -371,34 +393,40 @@
this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
}
}
+
+ private:
+ deque_base(const deque_base&);
protected:
+
void priv_initialize_map(std::size_t num_elements)
{
- std::size_t num_nodes = num_elements / deque_buf_size(sizeof(T)) + 1;
+// if(num_elements){
+ std::size_t num_nodes = num_elements / s_buffer_size() + 1;
- this->members_.m_map_size = max_value((std::size_t) InitialMapSize, num_nodes + 2);
- this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
+ this->members_.m_map_size = max_value((std::size_t) InitialMapSize, num_nodes + 2);
+ this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
- ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2;
- ptr_alloc_ptr nfinish = nstart + num_nodes;
-
- BOOST_TRY {
- this->priv_create_nodes(nstart, nfinish);
- }
- BOOST_CATCH(...){
- this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
- this->members_.m_map = 0;
- this->members_.m_map_size = 0;
- BOOST_RETHROW
- }
- BOOST_CATCH_END
+ ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2;
+ ptr_alloc_ptr nfinish = nstart + num_nodes;
+
+ BOOST_TRY {
+ this->priv_create_nodes(nstart, nfinish);
+ }
+ BOOST_CATCH(...){
+ this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
+ this->members_.m_map = 0;
+ this->members_.m_map_size = 0;
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
- this->members_.m_start.priv_set_node(nstart);
- this->members_.m_finish.priv_set_node(nfinish - 1);
- this->members_.m_start.m_cur = this->members_.m_start.m_first;
- this->members_.m_finish.m_cur = this->members_.m_finish.m_first +
- num_elements % deque_buf_size(sizeof(T));
+ this->members_.m_start.priv_set_node(nstart);
+ this->members_.m_finish.priv_set_node(nfinish - 1);
+ this->members_.m_start.m_cur = this->members_.m_start.m_first;
+ this->members_.m_finish.m_cur = this->members_.m_finish.m_first +
+ num_elements % s_buffer_size();
+// }
}
void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish)
@@ -495,10 +523,14 @@
typedef std::reverse_iterator<iterator> reverse_iterator;
/// @cond
- protected: // Internal typedefs
+ private: // Internal typedefs
typedef ptr_alloc_ptr index_pointer;
static std::size_t s_buffer_size()
- { return deque_buf_size(sizeof(T)); }
+ { return Base::s_buffer_size(); }
+ typedef detail::advanced_insert_aux_int<value_type, iterator> advanced_insert_aux_int_t;
+ typedef repeat_iterator<T, difference_type> r_iterator;
+ typedef detail::move_iterator<r_iterator> move_it;
+
/// @endcond
allocator_type get_allocator() const { return Base::alloc(); }
@@ -528,6 +560,18 @@
const_reverse_iterator rend() const
{ return const_reverse_iterator(this->members_.m_start); }
+ const_iterator cbegin() const
+ { return this->members_.m_start; }
+
+ const_iterator cend() const
+ { return this->members_.m_finish; }
+
+ const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(this->members_.m_finish); }
+
+ const_reverse_iterator crend() const
+ { return const_reverse_iterator(this->members_.m_start); }
+
reference operator[](size_type n)
{ return this->members_.m_start[difference_type(n)]; }
@@ -545,18 +589,12 @@
reference front() { return *this->members_.m_start; }
- reference back()
- {
- iterator tmp = this->members_.m_finish;
- --tmp;
- return *tmp;
- }
+ reference back() { return *(end()-1); }
const_reference front() const
{ return *this->members_.m_start; }
- const_reference back() const
- { const_iterator tmp = this->members_.m_finish; --tmp; return *tmp; }
+ const_reference back() const { return *(cend()-1); }
size_type size() const
{ return this->members_.m_finish - this->members_.m_start; }
@@ -565,10 +603,11 @@
{ return this->alloc().max_size(); }
bool empty() const
- { return this->members_.m_finish == this->members_.m_start; }
+ { return this->members_.m_finish == this->members_.m_start; }
explicit deque(const allocator_type& a = allocator_type())
- : Base(a, 0) {}
+ : Base(a)
+ {}
deque(const deque& x)
: Base(x.alloc(), x.size())
@@ -576,11 +615,11 @@
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
deque(const detail::moved_object<deque> &mx)
- : Base(mx.get())
+ : Base(mx.get().alloc())
{ this->swap(mx.get()); }
#else
deque(deque &&x)
- : Base(detail::move_impl(x))
+ : Base(x.alloc())
{ this->swap(x); }
#endif
@@ -593,8 +632,8 @@
// Check whether it's an integral type. If so, it's not an iterator.
template <class InpIt>
- deque(InpIt first, InpIt last,
- const allocator_type& a = allocator_type()) : Base(a)
+ deque(InpIt first, InpIt last, const allocator_type& a = allocator_type())
+ : Base(a)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = detail::is_convertible<InpIt, std::size_t>::value;
@@ -603,7 +642,9 @@
}
~deque()
- { priv_destroy_range(this->members_.m_start, this->members_.m_finish); }
+ {
+ priv_destroy_range(this->members_.m_start, this->members_.m_finish);
+ }
deque& operator= (const deque& x)
{
@@ -622,13 +663,22 @@
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
deque& operator= (const detail::moved_object<deque> &mx)
- { this->clear(); this->swap(mx.get()); return *this; }
+ {
+ deque &x = mx.get();
#else
- deque& operator= (deque &&mx)
- { this->clear(); this->swap(mx); return *this; }
+ deque& operator= (deque &&x)
+ {
#endif
+ this->clear();
+ this->swap(x);
+ return *this;
+ }
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(deque& x)
+ #else
+ void swap(deque &&x)
+ #endif
{
std::swap(this->members_.m_start, x.members_.m_start);
std::swap(this->members_.m_finish, x.members_.m_finish);
@@ -639,16 +689,14 @@
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<deque> &mx)
{ this->swap(mx.get()); }
- #else
- void swap(deque &&mx)
- { this->swap(mx); }
#endif
void assign(size_type n, const T& val)
{ this->priv_fill_assign(n, val); }
template <class InpIt>
- void assign(InpIt first, InpIt last) {
+ void assign(InpIt first, InpIt last)
+ {
//Dispatch depending on integer/iterator
const bool aux_boolean = detail::is_convertible<InpIt, std::size_t>::value;
typedef detail::bool_<aux_boolean> Result;
@@ -657,67 +705,59 @@
void push_back(const value_type& t)
{
- if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
- ++this->members_.m_finish.m_cur;
+ if(this->priv_push_back_simple_available()){
+ new(this->priv_push_back_simple_pos())value_type(t);
+ this->priv_push_back_simple_commit();
+ }
+ else{
+ this->priv_insert_aux(cend(), size_type(1), t);
}
- else
- this->priv_push_back_aux(t);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back(const detail::moved_object<value_type> &mt)
{
- if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
- ++this->members_.m_finish.m_cur;
- }
- else
- this->priv_push_back_aux(mt);
- }
+ value_type &t = mt.get();
#else
- void push_back(value_type &&mt)
+ void push_back(value_type &&t)
{
- if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(detail::move_impl(mt));
- ++this->members_.m_finish.m_cur;
+ #endif
+ if(this->priv_push_back_simple_available()){
+ new(this->priv_push_back_simple_pos())value_type(detail::move_impl(t));
+ this->priv_push_back_simple_commit();
+ }
+ else{
+ this->priv_insert_aux(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
- else
- this->priv_push_back_aux(detail::move_impl(mt));
}
- #endif
void push_front(const value_type& t)
{
- if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(t);
- --this->members_.m_start.m_cur;
+ if(this->priv_push_front_simple_available()){
+ new(this->priv_push_front_simple_pos())value_type(t);
+ this->priv_push_front_simple_commit();
+ }
+ else{
+ this->priv_insert_aux(cbegin(), size_type(1), t);
}
- else
- this->priv_push_front_aux(t);
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_front(const detail::moved_object<value_type> &mt)
{
- if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(mt);
- --this->members_.m_start.m_cur;
- }
- else
- this->priv_push_front_aux(mt);
- }
+ value_type &t = mt.get();
#else
- void push_front(value_type &&mt)
+ void push_front(value_type &&t)
{
- if (this->members_.m_start.m_cur != this->members_.m_start.m_first) {
- new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(detail::move_impl(mt));
- --this->members_.m_start.m_cur;
+ #endif
+ if(this->priv_push_front_simple_available()){
+ new(this->priv_push_front_simple_pos())value_type(detail::move_impl(t));
+ this->priv_push_front_simple_commit();
+ }
+ else{
+ this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
- else
- this->priv_push_front_aux(detail::move_impl(mt));
}
- #endif
void pop_back()
{
@@ -739,65 +779,53 @@
this->priv_pop_front_aux();
}
- iterator insert(iterator position, const value_type& x)
+ iterator insert(const_iterator position, const value_type& x)
{
- if (position.m_cur == this->members_.m_start.m_cur) {
+ if (position == cbegin()){
this->push_front(x);
- return this->members_.m_start;
+ return begin();
}
- else if (position.m_cur == this->members_.m_finish.m_cur) {
+ else if (position == cend()){
this->push_back(x);
- iterator tmp = this->members_.m_finish;
- --tmp;
- return tmp;
+ return (end()-1);
}
else {
- return this->priv_insert_aux(position, x);
+ size_type n = position - cbegin();
+ this->priv_insert_aux(position, size_type(1), x);
+ return iterator(this->begin() + n);
}
}
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<value_type> &mx)
+ iterator insert(const_iterator position, const detail::moved_object<value_type> &m)
{
- if (position.m_cur == this->members_.m_start.m_cur) {
- this->push_front(mx);
- return this->members_.m_start;
- }
- else if (position.m_cur == this->members_.m_finish.m_cur) {
- this->push_back(mx);
- iterator tmp = this->members_.m_finish;
- --tmp;
- return tmp;
- }
- else {
- return this->priv_insert_aux(position, mx);
- }
- }
+ value_type &mx = m.get();
#else
- iterator insert(iterator position, value_type &&mx)
+ iterator insert(const_iterator position, value_type &&mx)
{
- if (position.m_cur == this->members_.m_start.m_cur) {
+ #endif
+ if (position == cbegin()) {
this->push_front(detail::move_impl(mx));
- return this->members_.m_start;
+ return begin();
}
- else if (position.m_cur == this->members_.m_finish.m_cur) {
+ else if (position == cend()) {
this->push_back(detail::move_impl(mx));
- iterator tmp = this->members_.m_finish;
- --tmp;
- return tmp;
+ return(end()-1);
}
else {
- return this->priv_insert_aux(position, detail::move_impl(mx));
+ //Just call more general insert(pos, size, value) and return iterator
+ size_type n = position - begin();
+ this->priv_insert_aux(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
+ return iterator(this->begin() + n);
}
}
- #endif
- void insert(iterator pos, size_type n, const value_type& x)
- { this->priv_fill_insert(pos, n, x); }
+ void insert(const_iterator pos, size_type n, const value_type& x)
+ { this->priv_fill_insert(pos, n, x); }
// Check whether it's an integral type. If so, it's not an iterator.
template <class InpIt>
- void insert(iterator pos, InpIt first, InpIt last)
+ void insert(const_iterator pos, InpIt first, InpIt last)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = detail::is_convertible<InpIt, std::size_t>::value;
@@ -805,6 +833,158 @@
this->priv_insert_dispatch(pos, first, last, Result());
}
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template <class... Args>
+ void emplace_back(Args&&... args)
+ {
+ if(this->priv_push_back_simple_available()){
+ new(this->priv_push_back_simple_pos())value_type(detail::forward_impl<Args>(args)...);
+ this->priv_push_back_simple_commit();
+ }
+ else{
+ detail::advanced_insert_aux_emplace<T, iterator, Args...> proxy(detail::forward_impl<Args>(args)...);
+ this->priv_insert_aux_impl(this->cend(), 1, proxy);
+ }
+ }
+
+ template <class... Args>
+ void emplace_front(Args&&... args)
+ {
+ if(this->priv_push_front_simple_available()){
+ new(this->priv_push_front_simple_pos())value_type(detail::forward_impl<Args>(args)...);
+ this->priv_push_front_simple_commit();
+ }
+ else{
+ detail::advanced_insert_aux_emplace<T, iterator, Args...> proxy(detail::forward_impl<Args>(args)...);
+ this->priv_insert_aux_impl(this->cbegin(), 1, proxy);
+ }
+ }
+
+ template <class... Args>
+ iterator emplace(const_iterator p, Args&&... args)
+ {
+ if(p == this->cbegin()){
+ this->emplace_front(detail::forward_impl<Args>(args)...);
+ return this->begin();
+ }
+ else if(p == this->cend()){
+ this->emplace_back(detail::forward_impl<Args>(args)...);
+ return (this->end()-1);
+ }
+ else{
+ size_type n = p - this->cbegin();
+ detail::advanced_insert_aux_emplace<T, iterator, Args...> proxy(detail::forward_impl<Args>(args)...);
+ this->priv_insert_aux_impl(p, 1, proxy);
+ return iterator(this->begin() + n);
+ }
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //0 args
+ void emplace_back()
+ {
+ if(priv_push_front_simple_available()){
+ new(priv_push_front_simple_pos())value_type();
+ priv_push_front_simple_commit();
+ }
+ else{
+ detail::advanced_insert_aux_emplace<T, iterator> proxy;
+ priv_insert_aux_impl(cend(), 1, proxy);
+ }
+ }
+
+ void emplace_front()
+ {
+ if(priv_push_front_simple_available()){
+ new(priv_push_front_simple_pos())value_type();
+ priv_push_front_simple_commit();
+ }
+ else{
+ detail::advanced_insert_aux_emplace<T, iterator> proxy;
+ priv_insert_aux_impl(cbegin(), 1, proxy);
+ }
+ }
+
+ iterator emplace(const_iterator p)
+ {
+ if(p == cbegin()){
+ emplace_front();
+ return begin();
+ }
+ else if(p == cend()){
+ emplace_back();
+ return (end()-1);
+ }
+ else{
+ size_type n = p - cbegin();
+ detail::advanced_insert_aux_emplace<T, iterator> proxy;
+ priv_insert_aux_impl(p, 1, proxy);
+ return iterator(this->begin() + n);
+ }
+ }
+
+ //advanced_insert_int.hpp includes all necessary preprocessor machinery...
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ if(priv_push_back_simple_available()){ \
+ new(priv_push_back_simple_pos())value_type \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_push_back_simple_commit(); \
+ } \
+ else{ \
+ detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ <value_type, iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
+ proxy(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_insert_aux_impl(cend(), 1, proxy); \
+ } \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_front(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ if(priv_push_front_simple_available()){ \
+ new(priv_push_front_simple_pos())value_type \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_push_front_simple_commit(); \
+ } \
+ else{ \
+ detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ <value_type, iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
+ proxy(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_insert_aux_impl(cbegin(), 1, proxy); \
+ } \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ if(p == this->cbegin()){ \
+ this->emplace_front(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ return this->begin(); \
+ } \
+ else if(p == cend()){ \
+ this->emplace_back(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ return (this->end()-1); \
+ } \
+ else{ \
+ size_type pos_num = p - this->cbegin(); \
+ detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ <value_type, iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
+ proxy(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ this->priv_insert_aux_impl(p, 1, proxy); \
+ return iterator(this->begin() + pos_num); \
+ } \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
void resize(size_type new_size, const value_type& x)
{
const size_type len = size();
@@ -821,41 +1001,32 @@
this->erase(this->members_.m_start + new_size, this->members_.m_finish);
else{
size_type n = new_size - this->size();
- this->priv_reserve_elements_at_back(new_size);
-
- while(n--){
- //T default_constructed = detail::move_impl(T());
- T default_constructed;
-/* if(boost::is_scalar<T>::value){
- //Value initialization
- new(&default_constructed)T();
- }*/
- this->push_back(detail::move_impl(default_constructed));
- }
+ detail::default_construct_aux_proxy<T, iterator, size_type> proxy(n);
+ priv_insert_aux_impl(this->cend(), n, proxy);
}
}
- iterator erase(iterator pos)
+ iterator erase(const_iterator pos)
{
- iterator next = pos;
+ const_iterator next = pos;
++next;
difference_type index = pos - this->members_.m_start;
if (size_type(index) < (this->size() >> 1)) {
- std::copy_backward( detail::make_move_iterator(this->members_.m_start)
- , detail::make_move_iterator(pos)
- , next);
+ std::copy_backward( detail::make_move_iterator(begin())
+ , detail::make_move_iterator(iterator(pos))
+ , iterator(next));
pop_front();
}
else {
- std::copy( detail::make_move_iterator(next)
- , detail::make_move_iterator(this->members_.m_finish)
- , pos);
+ std::copy( detail::make_move_iterator(iterator(next))
+ , detail::make_move_iterator(end())
+ , iterator(pos));
pop_back();
}
return this->members_.m_start + index;
}
- iterator erase(iterator first, iterator last)
+ iterator erase(const_iterator first, const_iterator last)
{
if (first == this->members_.m_start && last == this->members_.m_finish) {
this->clear();
@@ -865,21 +1036,21 @@
difference_type n = last - first;
difference_type elems_before = first - this->members_.m_start;
if (elems_before < static_cast<difference_type>(this->size() - n) - elems_before) {
- std::copy_backward( detail::make_move_iterator(this->members_.m_start)
- , detail::make_move_iterator(first)
- , last);
+ std::copy_backward( detail::make_move_iterator(begin())
+ , detail::make_move_iterator(iterator(first))
+ , iterator(last));
iterator new_start = this->members_.m_start + n;
- if(!Base::trivial_dctr_after_move)
+ if(!Base::traits_t::trivial_dctr_after_move)
this->priv_destroy_range(this->members_.m_start, new_start);
this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
this->members_.m_start = new_start;
}
else {
- std::copy( detail::make_move_iterator(last)
- , detail::make_move_iterator(this->members_.m_finish)
- , first);
+ std::copy( detail::make_move_iterator(iterator(last))
+ , detail::make_move_iterator(end())
+ , iterator(first));
iterator new_finish = this->members_.m_finish - n;
- if(!Base::trivial_dctr_after_move)
+ if(!Base::traits_t::trivial_dctr_after_move)
this->priv_destroy_range(new_finish, this->members_.m_finish);
this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
this->members_.m_finish = new_finish;
@@ -911,56 +1082,58 @@
/// @cond
private:
- template <class InpIt>
- void insert(iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
- { std::copy(first, last, std::inserter(*this, pos)); }
+ bool priv_push_back_simple_available() const
+ {
+ return this->members_.m_map &&
+ (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1));
+ }
- template <class FwdIt>
- void insert(iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
+ void *priv_push_back_simple_pos() const
{
-
- size_type n = 0;
- n = std::distance(first, last);
+ return static_cast<void*>(detail::get_pointer(this->members_.m_finish.m_cur));
+ }
- if (pos.m_cur == this->members_.m_start.m_cur) {
- iterator new_start = this->priv_reserve_elements_at_front(n);
- BOOST_TRY{
- std::uninitialized_copy(first, last, new_start);
- this->members_.m_start = new_start;
- }
- BOOST_CATCH(...){
- this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
- else if (pos.m_cur == this->members_.m_finish.m_cur) {
- iterator new_finish = this->priv_reserve_elements_at_back(n);
- BOOST_TRY{
- std::uninitialized_copy(first, last, this->members_.m_finish);
- this->members_.m_finish = new_finish;
- }
- BOOST_CATCH(...){
- this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1);
- BOOST_RETHROW
- }
- BOOST_CATCH_END
+ void priv_push_back_simple_commit()
+ {
+ ++this->members_.m_finish.m_cur;
+ }
+
+ bool priv_push_front_simple_available() const
+ {
+ return this->members_.m_map &&
+ (this->members_.m_start.m_cur != this->members_.m_start.m_first);
+ }
+
+ void *priv_push_front_simple_pos() const
+ { return static_cast<void*>(detail::get_pointer(this->members_.m_start.m_cur) - 1); }
+
+ void priv_push_front_simple_commit()
+ { --this->members_.m_start.m_cur; }
+
+ template <class InpIt>
+ void priv_insert_aux(const_iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
+ {
+ for(;first != last; ++first){
+ this->insert(pos, move_impl(value_type(*first)));
}
- else
- this->priv_insert_aux(pos, first, last, n);
}
+ template <class FwdIt>
+ void priv_insert_aux(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
+ { this->priv_insert_aux(pos, first, last); }
+
// assign(), a generalized assignment member function. Two
// versions: one that takes a count, and one that takes a range.
// The range version is a member template, so we dispatch on whether
// or not the type is an integer.
- void priv_fill_assign(size_type n, const T& val) {
+ void priv_fill_assign(size_type n, const T& val)
+ {
if (n > size()) {
std::fill(begin(), end(), val);
- this->insert(end(), n - size(), val);
+ this->insert(cend(), n - size(), val);
}
else {
- this->erase(begin() + n, end());
+ this->erase(cbegin() + n, cend());
std::fill(begin(), end(), val);
}
}
@@ -1009,112 +1182,80 @@
for ( ; first != last && cur != end(); ++cur, ++first)
*cur = *first;
if (first == last)
- this->erase(cur, end());
+ this->erase(cur, cend());
else
- this->insert(end(), first, last);
+ this->insert(cend(), first, last);
}
template <class FwdIt>
- void priv_assign_aux(FwdIt first, FwdIt last,
- std::forward_iterator_tag) {
- size_type len = 0;
- std::distance(first, last, len);
+ void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
+ {
+ size_type len = std::distance(first, last);
if (len > size()) {
FwdIt mid = first;
std::advance(mid, size());
std::copy(first, mid, begin());
- this->insert(end(), mid, last);
+ this->insert(cend(), mid, last);
}
else
- this->erase(std::copy(first, last, begin()), end());
+ this->erase(std::copy(first, last, begin()), cend());
}
template <class Integer>
- void priv_insert_dispatch(iterator pos, Integer n, Integer x,
- detail::true_)
- {
- this->priv_fill_insert(pos, (size_type) n, (value_type) x);
- }
+ void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, detail::true_)
+ { this->priv_fill_insert(pos, (size_type) n, (value_type) x); }
template <class InpIt>
- void priv_insert_dispatch(iterator pos,
- InpIt first, InpIt last,
- detail::false_)
+ void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
- this->insert(pos, first, last, ItCat());
+ this->priv_insert_aux(pos, first, last, ItCat());
}
- iterator priv_insert_aux(iterator pos, const value_type& x)
+ void priv_insert_aux(const_iterator pos, size_type n, const value_type& x)
{
- size_type n = pos - begin();
- this->priv_insert_aux(pos, size_type(1), x);
- return iterator(this->begin() + n);
+ typedef constant_iterator<value_type, difference_type> c_it;
+ this->priv_insert_aux(pos, c_it(x, n), c_it());
}
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator priv_insert_aux(iterator pos, const detail::moved_object<value_type> &mx)
- {
- typedef repeat_iterator<T, difference_type> r_iterator;
- typedef detail::move_iterator<r_iterator> move_it;
- //Just call more general insert(pos, size, value) and return iterator
- size_type n = pos - begin();
- this->insert(pos
- ,move_it(r_iterator(mx.get(), 1))
- ,move_it(r_iterator()));
- return iterator(this->begin() + n);
- }
- #else
- iterator priv_insert_aux(iterator pos, value_type &&mx)
+ //Just forward all operations to priv_insert_aux_impl
+ template <class FwdIt>
+ void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
{
- typedef repeat_iterator<T, difference_type> r_iterator;
- typedef detail::move_iterator<r_iterator> move_it;
- //Just call more general insert(pos, size, value) and return iterator
- size_type n = pos - begin();
- this->insert(pos
- ,move_it(r_iterator(mx, 1))
- ,move_it(r_iterator()));
- return iterator(this->begin() + n);
+ detail::advanced_insert_aux_proxy<T, FwdIt, iterator> proxy(first, last);
+ priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
- #endif
- void priv_insert_aux(iterator pos, size_type n, const value_type& x)
+ void priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
{
- typedef constant_iterator<value_type, difference_type> c_it;
- this->insert(pos, c_it(x, n), c_it());
- }
+ iterator pos(p);
+ if(!this->members_.m_map){
+ this->priv_initialize_map(0);
+ pos = this->begin();
+ }
- template <class FwdIt>
- void priv_insert_aux(iterator pos, FwdIt first, FwdIt last, size_type n)
- {
const difference_type elemsbefore = pos - this->members_.m_start;
- size_type length = size();
+ size_type length = this->size();
if (elemsbefore < static_cast<difference_type>(length / 2)) {
iterator new_start = this->priv_reserve_elements_at_front(n);
iterator old_start = this->members_.m_start;
pos = this->members_.m_start + elemsbefore;
- BOOST_TRY {
- if (elemsbefore >= difference_type(n)) {
- iterator start_n = this->members_.m_start + difference_type(n);
- std::uninitialized_copy(detail::make_move_iterator(this->members_.m_start), detail::make_move_iterator(start_n), new_start);
- this->members_.m_start = new_start;
- std::copy(detail::make_move_iterator(start_n), detail::make_move_iterator(pos), old_start);
- std::copy(first, last, pos - difference_type(n));
- }
- else {
- FwdIt mid = first;
- std::advance(mid, difference_type(n) - elemsbefore);
- this->priv_uninitialized_copy_copy
- (detail::make_move_iterator(this->members_.m_start), detail::make_move_iterator(pos), first, mid, new_start);
- this->members_.m_start = new_start;
- std::copy(mid, last, old_start);
- }
+ if (elemsbefore >= difference_type(n)) {
+ iterator start_n = this->members_.m_start + difference_type(n);
+ std::uninitialized_copy(detail::make_move_iterator(this->members_.m_start), detail::make_move_iterator(start_n), new_start);
+ this->members_.m_start = new_start;
+ std::copy(detail::make_move_iterator(start_n), detail::make_move_iterator(pos), old_start);
+ interf.copy_all_to(pos - difference_type(n));
}
- BOOST_CATCH(...){
- this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
- BOOST_RETHROW
+ else {
+ difference_type mid_count = (difference_type(n) - elemsbefore);
+ iterator mid_start = old_start - mid_count;
+ interf.uninitialized_copy_some_and_update(mid_start, mid_count, true);
+ this->members_.m_start = mid_start;
+ std::uninitialized_copy(detail::make_move_iterator(old_start), detail::make_move_iterator(pos), new_start);
+ this->members_.m_start = new_start;
+ interf.copy_all_to(old_start);
}
- BOOST_CATCH_END
}
else {
iterator new_finish = this->priv_reserve_elements_at_back(n);
@@ -1122,31 +1263,24 @@
const difference_type elemsafter =
difference_type(length) - elemsbefore;
pos = this->members_.m_finish - elemsafter;
- BOOST_TRY {
- if (elemsafter > difference_type(n)) {
- iterator finish_n = this->members_.m_finish - difference_type(n);
- std::uninitialized_copy(detail::make_move_iterator(finish_n), detail::make_move_iterator(this->members_.m_finish), this->members_.m_finish);
- this->members_.m_finish = new_finish;
- std::copy_backward(detail::make_move_iterator(pos), detail::make_move_iterator(finish_n), old_finish);
- std::copy(first, last, pos);
- }
- else {
- FwdIt mid = first;
- std::advance(mid, elemsafter);
- this->priv_uninitialized_copy_copy(mid, last, detail::make_move_iterator(pos), detail::make_move_iterator(this->members_.m_finish), this->members_.m_finish);
- this->members_.m_finish = new_finish;
- std::copy(first, mid, pos);
- }
+ if (elemsafter >= difference_type(n)) {
+ iterator finish_n = this->members_.m_finish - difference_type(n);
+ std::uninitialized_copy(detail::make_move_iterator(finish_n), detail::make_move_iterator(this->members_.m_finish), this->members_.m_finish);
+ this->members_.m_finish = new_finish;
+ std::copy_backward(detail::make_move_iterator(pos), detail::make_move_iterator(finish_n), old_finish);
+ interf.copy_all_to(pos);
}
- BOOST_CATCH(...){
- this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1);
- BOOST_RETHROW
+ else {
+ interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
+ this->members_.m_finish += n-elemsafter;
+ std::uninitialized_copy(detail::make_move_iterator(pos), detail::make_move_iterator(old_finish), this->members_.m_finish);
+ this->members_.m_finish = new_finish;
+ interf.copy_all_to(pos);
}
- BOOST_CATCH_END
}
}
- void priv_fill_insert(iterator pos, size_type n, const value_type& x)
+ void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
this->insert(pos, c_it(x, n), c_it());
@@ -1211,112 +1345,6 @@
BOOST_CATCH_END
}
- // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_last - 1.
- void priv_push_back_aux(const value_type& t = value_type())
- {
- this->priv_reserve_map_at_back();
- *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
- BOOST_TRY {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t);
- this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
- this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
- }
- BOOST_CATCH(...){
- this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_last - 1.
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- void priv_push_back_aux(const detail::moved_object<value_type> &mt)
- {
- this->priv_reserve_map_at_back();
- *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
- BOOST_TRY {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt);
- this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
- this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
- }
- BOOST_CATCH(...){
- this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
- #else
- void priv_push_back_aux(value_type &&mt)
- {
- this->priv_reserve_map_at_back();
- *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node();
- BOOST_TRY {
- new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(detail::move_impl(mt));
- this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1);
- this->members_.m_finish.m_cur = this->members_.m_finish.m_first;
- }
- BOOST_CATCH(...){
- this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
- #endif
-
- // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_first.
- void priv_push_front_aux(const value_type& t)
- {
- this->priv_reserve_map_at_front();
- *(this->members_.m_start.m_node - 1) = this->priv_allocate_node();
- BOOST_TRY {
- this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
- this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(t);
- }
- BOOST_CATCH(...){
- ++this->members_.m_start;
- this->priv_deallocate_node(*(this->members_.m_start.m_node - 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- void priv_push_front_aux(const detail::moved_object<value_type> &mt)
- {
- this->priv_reserve_map_at_front();
- *(this->members_.m_start.m_node - 1) = this->priv_allocate_node();
- BOOST_TRY {
- this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
- this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(mt);
- }
- BOOST_CATCH(...){
- ++this->members_.m_start;
- this->priv_deallocate_node(*(this->members_.m_start.m_node - 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
- #else
- void priv_push_front_aux(value_type &&mt)
- {
- this->priv_reserve_map_at_front();
- *(this->members_.m_start.m_node - 1) = this->priv_allocate_node();
- BOOST_TRY {
- this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1);
- this->members_.m_start.m_cur = this->members_.m_start.m_last - 1;
- new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(detail::move_impl(mt));
- }
- BOOST_CATCH(...){
- ++this->members_.m_start;
- this->priv_deallocate_node(*(this->members_.m_start.m_node - 1));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
- #endif
-
// Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first.
void priv_pop_back_aux()
{
@@ -1341,68 +1369,52 @@
iterator priv_reserve_elements_at_front(size_type n)
{
size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first;
- if (n > vacancies)
- this->priv_new_elements_at_front(n - vacancies);
+ if (n > vacancies){
+ size_type new_elems = n-vacancies;
+ size_type new_nodes = (new_elems + this->s_buffer_size() - 1) /
+ this->s_buffer_size();
+ size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map);
+ if (new_nodes > s){
+ this->priv_reallocate_map(new_nodes, true);
+ }
+ size_type i = 1;
+ BOOST_TRY {
+ for (; i <= new_nodes; ++i)
+ *(this->members_.m_start.m_node - i) = this->priv_allocate_node();
+ }
+ BOOST_CATCH(...) {
+ for (size_type j = 1; j < i; ++j)
+ this->priv_deallocate_node(*(this->members_.m_start.m_node - j));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
return this->members_.m_start - difference_type(n);
}
iterator priv_reserve_elements_at_back(size_type n)
{
size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1;
- if (n > vacancies)
- this->priv_new_elements_at_back(n - vacancies);
- return this->members_.m_finish + difference_type(n);
- }
-
- void priv_new_elements_at_front(size_type new_elems)
- {
- size_type new_nodes = (new_elems + this->s_buffer_size() - 1) /
- this->s_buffer_size();
- this->priv_reserve_map_at_front(new_nodes);
- size_type i = 1;
- BOOST_TRY {
- for (; i <= new_nodes; ++i)
- *(this->members_.m_start.m_node - i) = this->priv_allocate_node();
- }
- BOOST_CATCH(...) {
- for (size_type j = 1; j < i; ++j)
- this->priv_deallocate_node(*(this->members_.m_start.m_node - j));
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- void priv_new_elements_at_back(size_type new_elems)
- {
- size_type new_nodes = (new_elems + this->s_buffer_size() - 1)
- / this->s_buffer_size();
- this->priv_reserve_map_at_back(new_nodes);
- size_type i;
- BOOST_TRY {
- for (i = 1; i <= new_nodes; ++i)
- *(this->members_.m_finish.m_node + i) = this->priv_allocate_node();
- }
- BOOST_CATCH(...) {
- for (size_type j = 1; j < i; ++j)
- this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));
- BOOST_RETHROW
+ if (n > vacancies){
+ size_type new_elems = n - vacancies;
+ size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size();
+ size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map));
+ if (new_nodes + 1 > s){
+ this->priv_reallocate_map(new_nodes, false);
+ }
+ size_type i;
+ BOOST_TRY {
+ for (i = 1; i <= new_nodes; ++i)
+ *(this->members_.m_finish.m_node + i) = this->priv_allocate_node();
+ }
+ BOOST_CATCH(...) {
+ for (size_type j = 1; j < i; ++j)
+ this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
}
- BOOST_CATCH_END
- }
-
- // Makes sure the this->members_.m_map has space for new nodes. Does not actually
- // add the nodes. Can invalidate this->members_.m_map pointers. (And consequently,
- // deque iterators.)
- void priv_reserve_map_at_back (size_type nodes_to_add = 1)
- {
- if (nodes_to_add + 1 > this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map))
- this->priv_reallocate_map(nodes_to_add, false);
- }
-
- void priv_reserve_map_at_front (size_type nodes_to_add = 1)
- {
- if (nodes_to_add > size_type(this->members_.m_start.m_node - this->members_.m_map))
- this->priv_reallocate_map(nodes_to_add, true);
+ return this->members_.m_finish + difference_type(n);
}
void priv_reallocate_map(size_type nodes_to_add, bool add_at_front)
@@ -1437,68 +1449,6 @@
this->members_.m_start.priv_set_node(new_nstart);
this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
}
-
- // this->priv_uninitialized_copy_fill
- // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and
- // fills [first2 + (last1 - first1), last2) with x.
- void priv_uninitialized_copy_fill(iterator first1, iterator last1,
- iterator first2, iterator last2,
- const T& x)
- {
- iterator mid2 = std::uninitialized_copy(first1, last1, first2);
- BOOST_TRY {
- std::uninitialized_fill(mid2, last2, x);
- }
- BOOST_CATCH(...){
- for(;first2 != mid2; ++first2){
- detail::get_pointer(&*first2)->~value_type();
- }
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- // this->priv_uninitialized_fill_copy
- // Fills [result, mid) with x, and copies [first, last) into
- // [mid, mid + (last - first)).
- iterator priv_uninitialized_fill_copy(iterator result, iterator mid,
- const T& x,
- iterator first, iterator last)
- {
- std::uninitialized_fill(result, mid, x);
- BOOST_TRY {
- return std::uninitialized_copy(first, last, mid);
- }
- BOOST_CATCH(...){
- for(;result != mid; ++result){
- detail::get_pointer(&*result)->~value_type();
- }
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- // this->priv_uninitialized_copy_copy
- // Copies [first1, last1) into [result, result + (last1 - first1)), and
- // copies [first2, last2) into
- // [result, result + (last1 - first1) + (last2 - first2)).
- template <class InpIt1, class InpIt2, class FwdIt>
- FwdIt priv_uninitialized_copy_copy(InpIt1 first1, InpIt1 last1,
- InpIt2 first2, InpIt2 last2,
- FwdIt result)
- {
- FwdIt mid = std::uninitialized_copy(first1, last1, result);
- BOOST_TRY {
- return std::uninitialized_copy(first2, last2, mid);
- }
- BOOST_CATCH(...){
- for(;result != mid; ++result){
- detail::get_pointer(&*result)->~value_type();
- }
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
/// @endcond
};
Modified: trunk/boost/interprocess/containers/detail/flat_tree.hpp
==============================================================================
--- trunk/boost/interprocess/containers/detail/flat_tree.hpp (original)
+++ trunk/boost/interprocess/containers/detail/flat_tree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -175,25 +175,37 @@
{ return this->m_data.m_vect.begin(); }
const_iterator begin() const
+ { return this->cbegin(); }
+
+ const_iterator cbegin() const
{ return this->m_data.m_vect.begin(); }
iterator end()
{ return this->m_data.m_vect.end(); }
const_iterator end() const
+ { return this->cend(); }
+
+ const_iterator cend() const
{ return this->m_data.m_vect.end(); }
reverse_iterator rbegin()
{ return reverse_iterator(this->end()); }
const_reverse_iterator rbegin() const
- { return const_reverse_iterator(this->end()); }
+ { return this->crbegin(); }
+
+ const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(this->cend()); }
reverse_iterator rend()
{ return reverse_iterator(this->begin()); }
const_reverse_iterator rend() const
- { return const_reverse_iterator(this->begin()); }
+ { return this->crend(); }
+
+ const_reverse_iterator crend() const
+ { return const_reverse_iterator(this->cbegin()); }
bool empty() const
{ return this->m_data.m_vect.empty(); }
@@ -237,24 +249,18 @@
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
std::pair<iterator,bool> insert_unique(const detail::moved_object<value_type>& mval)
{
- insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(mval.get(), data);
- if(ret.second){
- ret.first = priv_insert_commit(data, mval);
- }
- return ret;
- }
+ value_type &val = mval.get();
#else
- std::pair<iterator,bool> insert_unique(value_type && mval)
+ std::pair<iterator,bool> insert_unique(value_type && val)
{
+ #endif
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(mval, data);
+ std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
if(ret.second){
- ret.first = priv_insert_commit(data, detail::move_impl(mval));
+ ret.first = priv_insert_commit(data, detail::move_impl(val));
}
return ret;
}
- #endif
iterator insert_equal(const value_type& val)
@@ -350,6 +356,146 @@
priv_insert_equal(first, last, ItCat());
}
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template <class... Args>
+ iterator emplace_unique(Args&&... args)
+ {
+ value_type val(detail::forward_impl<Args>(args)...);
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ priv_insert_unique_prepare(val, data);
+ if(ret.second){
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+ return ret.first;
+ }
+
+ template <class... Args>
+ iterator emplace_hint_unique(const_iterator hint, Args&&... args)
+ {
+ value_type val(detail::forward_impl<Args>(args)...);
+ insert_commit_data data;
+ std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
+ if(ret.second){
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+ return ret.first;
+ }
+
+ template <class... Args>
+ iterator emplace_equal(Args&&... args)
+ {
+ value_type val(detail::forward_impl<Args>(args)...);
+ iterator i = this->upper_bound(KeyOfValue()(val));
+ i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
+ return i;
+ }
+
+ template <class... Args>
+ iterator emplace_hint_equal(const_iterator hint, Args&&... args)
+ {
+ value_type val(detail::forward_impl<Args>(args)...);
+ insert_commit_data data;
+ priv_insert_equal_prepare(hint, val, data);
+ return priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace_unique()
+ {
+ detail::value_init<value_type> vval;
+ value_type &val = vval.m_t;
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ priv_insert_unique_prepare(val, data);
+ if(ret.second){
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+ return ret.first;
+ }
+
+ iterator emplace_hint_unique(const_iterator hint)
+ {
+ detail::value_init<value_type> vval;
+ value_type &val = vval.m_t;
+ insert_commit_data data;
+ std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
+ if(ret.second){
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+ return ret.first;
+ }
+
+ iterator emplace_equal()
+ {
+ detail::value_init<value_type> vval;
+ value_type &val = vval.m_t;
+ iterator i = this->upper_bound(KeyOfValue()(val));
+ i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val));
+ return i;
+ }
+
+ iterator emplace_hint_equal(const_iterator hint)
+ {
+ detail::value_init<value_type> vval;
+ value_type &val = vval.m_t;
+ insert_commit_data data;
+ priv_insert_equal_prepare(hint, val, data);
+ return priv_insert_commit(data, detail::move_impl<value_type>(val));
+ }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ insert_commit_data data; \
+ std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
+ if(ret.second){ \
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
+ } \
+ return ret.first; \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint_unique(const_iterator hint, \
+ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ insert_commit_data data; \
+ std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
+ if(ret.second){ \
+ ret.first = priv_insert_commit(data, detail::move_impl<value_type>(val)); \
+ } \
+ return ret.first; \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ iterator i = this->upper_bound(KeyOfValue()(val)); \
+ i = this->m_data.m_vect.insert(i, detail::move_impl<value_type>(val)); \
+ return i; \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint_equal(const_iterator hint, \
+ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ value_type val(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ insert_commit_data data; \
+ priv_insert_equal_prepare(hint, val, data); \
+ return priv_insert_commit(data, detail::move_impl<value_type>(val)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
iterator erase(const_iterator position)
{ return this->m_data.m_vect.erase(position); }
@@ -435,14 +581,13 @@
private:
struct insert_commit_data
{
- iterator position;
+ const_iterator position;
};
// insert/erase
void priv_insert_equal_prepare
- (const_iterator p, const value_type& val, insert_commit_data &data)
+ (const_iterator pos, const value_type& val, insert_commit_data &data)
{
- iterator &pos = (iterator &)(const_iterator &)p;
// N1780
// To insert val at pos:
// if pos == end || val <= *pos
@@ -456,13 +601,13 @@
// insert val before lower_bound(val)
const value_compare &value_comp = this->m_data;
- if(pos == this->end() || !value_comp(*pos, val)){
- if (pos == this->begin() || !value_comp(val, pos[-1])){
+ if(pos == this->cend() || !value_comp(*pos, val)){
+ if (pos == this->cbegin() || !value_comp(val, pos[-1])){
data.position = pos;
}
else{
data.position =
- this->priv_upper_bound(this->begin(), pos, KeyOfValue()(val));
+ this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
}
}
//Works, but increases code complexity
@@ -471,17 +616,17 @@
//}
else{
data.position =
- this->priv_lower_bound(pos, this->end(), KeyOfValue()(val));
+ this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
}
}
std::pair<iterator,bool> priv_insert_unique_prepare
- (iterator beg, iterator end, const value_type& val, insert_commit_data &commit_data)
+ (const_iterator beg, const_iterator end, const value_type& val, insert_commit_data &commit_data)
{
const value_compare &value_comp = this->m_data;
commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val));
return std::pair<iterator,bool>
- ( commit_data.position
+ ( *reinterpret_cast<iterator*>(&commit_data.position)
, commit_data.position == end || value_comp(val, *commit_data.position));
}
@@ -490,9 +635,8 @@
{ return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
std::pair<iterator,bool> priv_insert_unique_prepare
- (const_iterator p, const value_type& val, insert_commit_data &commit_data)
+ (const_iterator pos, const value_type& val, insert_commit_data &commit_data)
{
- iterator &pos = (iterator &)(const_iterator &)p;
//N1780. Props to Howard Hinnant!
//To insert val at pos:
//if pos == end || val <= *pos
@@ -506,17 +650,17 @@
// insert val before lower_bound(val)
const value_compare &value_comp = this->m_data;
- if(pos == this->end() || value_comp(val, *pos)){
- if(pos != this->begin() && !value_comp(val, pos[-1])){
+ if(pos == this->cend() || value_comp(val, *pos)){
+ if(pos != this->cbegin() && !value_comp(val, pos[-1])){
if(value_comp(pos[-1], val)){
- commit_data.position = iterator(pos);
- return std::pair<iterator,bool>(pos, true);
+ commit_data.position = pos;
+ return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), true);
}
else{
- return std::pair<iterator,bool>(pos, false);
+ return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
}
}
- return this->priv_insert_unique_prepare(this->begin(), pos, val, commit_data);
+ return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
}
// Works, but increases code complexity
Modified: trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp
==============================================================================
--- trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp (original)
+++ trunk/boost/interprocess/containers/detail/node_alloc_holder.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -54,7 +54,7 @@
{ return static_cast<const ValueCompare &>(*this); }
bool operator()(const Node &a, const Node &b) const
- { return ValueCompare::operator()(a.m_data, b.m_data); }
+ { return ValueCompare::operator()(a.get_data(), b.get_data()); }
};
template<class A, class ICont>
@@ -143,22 +143,8 @@
{ this->node_alloc().deallocate_one(p); }
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template<class Convertible>
- static void construct(const NodePtr &ptr, const Convertible &value)
- { new((void*)detail::get_pointer(ptr)) Node(value); }
- #else
- template<class Convertible>
- static void construct(const NodePtr &ptr, Convertible &&value)
- { new((void*)detail::get_pointer(ptr)) Node(detail::forward_impl<Convertible>(value)); }
- #endif
-
- static void construct(const NodePtr &ptr)
- { new((void*)detail::get_pointer(ptr)) Node(); }
-
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class Convertible1, class Convertible2>
- static void construct(const NodePtr &ptr,
- const detail::moved_object<std::pair<Convertible1, Convertible2> > &value)
+ static void construct(const NodePtr &ptr, const detail::moved_object<std::pair<Convertible1, Convertible2> > &value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
@@ -168,7 +154,7 @@
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
- value_type *valueptr = &nodeptr->m_data;
+ value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.get().first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.get().second));
@@ -182,8 +168,7 @@
}
#else
template<class Convertible1, class Convertible2>
- static void construct(const NodePtr &ptr,
- std::pair<Convertible1, Convertible2> &&value)
+ static void construct(const NodePtr &ptr, std::pair<Convertible1, Convertible2> &&value)
{
typedef typename Node::hook_type hook_type;
typedef typename Node::value_type::first_type first_type;
@@ -193,7 +178,7 @@
//Hook constructor does not throw
new(static_cast<hook_type*>(nodeptr))hook_type();
//Now construct pair members_holder
- value_type *valueptr = &nodeptr->m_data;
+ value_type *valueptr = &nodeptr->get_data();
new((void*)&valueptr->first) first_type(detail::move_impl(value.first));
BOOST_TRY{
new((void*)&valueptr->second) second_type(detail::move_impl(value.second));
@@ -210,43 +195,82 @@
static void destroy(const NodePtr &ptr)
{ detail::get_pointer(ptr)->~Node(); }
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template<class Convertible>
- NodePtr create_node(const Convertible& x)
+
+ #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ Deallocator
+ #else
+ move_return<Deallocator>
+ #endif
+ create_node_and_deallocator()
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
- self_t::construct(p, x);
- node_deallocator.release();
- return (p);
+ return node_deallocator;
}
- #else
- template<class Convertible>
- NodePtr create_node(Convertible &&x)
+
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class ...Args>
+ static void construct(const NodePtr &ptr, Args &&...args)
+ { new((void*)detail::get_pointer(ptr)) Node(detail::forward_impl<Args>(args)...); }
+
+ template<class ...Args>
+ NodePtr create_node(Args &&...args)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
- self_t::construct(p, detail::forward_impl<Convertible>(x));
+ self_t::construct(p, detail::forward_impl<Args>(args)...);
node_deallocator.release();
return (p);
}
- #endif
- template<class It>
- NodePtr create_node_from_it(It it)
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ static void construct(const NodePtr &ptr)
+ { new((void*)detail::get_pointer(ptr)) Node(); }
+
+ NodePtr create_node()
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
- ::boost::interprocess::construct_in_place(detail::get_pointer(p), it);
+ self_t::construct(p);
node_deallocator.release();
return (p);
}
- NodePtr create_node()
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void construct(const NodePtr &ptr, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ new((void*)detail::get_pointer(ptr)) \
+ Node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ NodePtr create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ NodePtr p = this->allocate_one(); \
+ Deallocator node_deallocator(p, this->node_alloc()); \
+ self_t::construct(p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ node_deallocator.release(); \
+ return (p); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class It>
+ NodePtr create_node_from_it(It it)
{
NodePtr p = this->allocate_one();
Deallocator node_deallocator(p, this->node_alloc());
- self_t::construct(p);
+ ::boost::interprocess::construct_in_place(detail::get_pointer(p), it);
node_deallocator.release();
return (p);
}
@@ -339,7 +363,7 @@
{}
NodePtr operator()(const Node &other) const
- { return m_holder.create_node(other.m_data); }
+ { return m_holder.create_node(other.get_data()); }
node_alloc_holder &m_holder;
};
Modified: trunk/boost/interprocess/containers/detail/tree.hpp
==============================================================================
--- trunk/boost/interprocess/containers/detail/tree.hpp (original)
+++ trunk/boost/interprocess/containers/detail/tree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -52,7 +52,11 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/interprocess/containers/detail/node_alloc_holder.hpp>
#include <boost/intrusive/rbtree.hpp>
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#endif
+#include <utility> //std::pair
#include <iterator>
#include <algorithm>
@@ -84,39 +88,79 @@
{ return key_compare::operator()(KeyOfValue()(a), KeyOfValue()(b)); }
};
-template <class T, class VoidPointer>
-struct rbtree_node
- : public bi::make_set_base_hook
- < bi::void_pointer<VoidPointer>
- , bi::link_mode<bi::normal_link>
- , bi::optimize_size<true>
- >::type
+template<class VoidPointer>
+struct rbtree_hook
{
typedef typename bi::make_set_base_hook
< bi::void_pointer<VoidPointer>
, bi::link_mode<bi::normal_link>
, bi::optimize_size<true>
- >::type hook_type;
+ >::type type;
+};
+
+template<class T>
+struct rbtree_type
+{
+ typedef T type;
+};
+
+template<class T1, class T2>
+struct rbtree_type< std::pair<T1, T2> >
+{
+ typedef detail::pair<T1, T2> type;
+};
+
+template <class T, class VoidPointer>
+struct rbtree_node
+ : public rbtree_hook<VoidPointer>::type
+{
+ typedef typename rbtree_hook<VoidPointer>::type hook_type;
typedef T value_type;
+ typedef typename rbtree_type<T>::type internal_type;
typedef rbtree_node<T, VoidPointer> node_type;
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template<class Convertible>
- rbtree_node(const Convertible &conv)
- : m_data(conv){}
- #else
- template<class Convertible>
- rbtree_node(Convertible &&conv)
- : m_data(detail::forward_impl<Convertible>(conv)){}
- #endif
+ #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ rbtree_node()
+ : m_data()
+ {}
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ rbtree_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ : m_data(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
+ {} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #else //#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class ...Args>
+ rbtree_node(Args &&...args)
+ : m_data(detail::forward_impl<Args>(args)...)
+ {}
+ #endif//#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
rbtree_node &operator=(const rbtree_node &other)
{ do_assign(other.m_data); return *this; }
- T m_data;
- private:
+ T &get_data()
+ {
+ T* ptr = reinterpret_cast<T*>(&this->m_data);
+ return *ptr;
+ }
+
+ const T &get_data() const
+ {
+ const T* ptr = reinterpret_cast<const T*>(&this->m_data);
+ return *ptr;
+ }
+
+ private:
+ internal_type m_data;
template<class A, class B>
void do_assign(const std::pair<const A, B> &p)
@@ -125,49 +169,27 @@
m_data.second = p.second;
}
+ template<class A, class B>
+ void do_assign(const detail::pair<const A, B> &p)
+ {
+ const_cast<A&>(m_data.first) = p.first;
+ m_data.second = p.second;
+ }
+
template<class V>
void do_assign(const V &v)
{ m_data = v; }
public:
- #if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE)
-
- template<class Convertible>
- static void construct(node_type *ptr, const Convertible &value)
- { new(ptr) node_type(value); }
-
- template<class Convertible1, class Convertible2>
- static void construct(node_type *ptr,
- const detail::moved_object<std::pair<Convertible1, Convertible2> > &value)
- {
- //std::pair is not movable so we define our own type and overwrite it
- typedef detail::pair<typename node_type::value_type::first_type
- ,typename node_type::value_type::second_type> hack_pair_t;
-
- typedef rbtree_node<hack_pair_t, VoidPointer> hack_node_t;
-
- new((void*)ptr) hack_node_t(value);
- }
-
- #elif !defined(BOOST_INTERPROCESS_RVALUE_PAIR)
-
template<class Convertible>
- static void construct(node_type *ptr, Convertible &&value)
- { new(ptr) node_type(detail::forward_impl<Convertible>(value)); }
-
- template<class Convertible1, class Convertible2>
- static void construct(node_type *ptr,
- std::pair<Convertible1, Convertible2> &&value)
- {
- //std::pair is not movable so we define our own type and overwrite it
- typedef detail::pair<typename node_type::value_type::first_type
- ,typename node_type::value_type::second_type> hack_pair_t;
- typedef rbtree_node<hack_pair_t, VoidPointer> hack_node_t;
-
- new((void*)ptr) hack_node_t(value);
- }
+ static void construct(node_type *ptr
+ #if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE)
+ , const Convertible &value)
+ #else
+ , Convertible &&value)
#endif
+ { new(ptr) node_type(detail::forward_impl<Convertible>(value)); }
};
}//namespace detail {
@@ -193,7 +215,7 @@
typedef typename bi::make_rbtree
<node_type
,bi::compare<node_compare_type>
- ,bi::base_hook<typename node_type::hook_type>
+ ,bi::base_hook<typename rbtree_hook<void_pointer>::type>
,bi::constant_time_size<true>
,bi::size_type<typename A::size_type>
>::type container_type;
@@ -302,11 +324,11 @@
template<class KeyType>
bool operator()(const Node &n, const KeyType &k) const
- { return KeyValueCompare::operator()(n.m_data, k); }
+ { return KeyValueCompare::operator()(n.get_data(), k); }
template<class KeyType>
bool operator()(const KeyType &k, const Node &n) const
- { return KeyValueCompare::operator()(k, n.m_data); }
+ { return KeyValueCompare::operator()(k, n.get_data()); }
};
typedef key_node_compare<value_compare> KeyNodeCompare;
@@ -341,10 +363,10 @@
//Pointer like operators
const_reference operator*() const
- { return m_it->m_data; }
+ { return m_it->get_data(); }
const_pointer operator->() const
- { return const_pointer(&m_it->m_data); }
+ { return const_pointer(&m_it->get_data()); }
//Increment / Decrement
const_iterator& operator++()
@@ -387,8 +409,8 @@
iterator(){}
//Pointer like operators
- reference operator*() const { return this->m_it->m_data; }
- pointer operator->() const { return pointer(&this->m_it->m_data); }
+ reference operator*() const { return this->m_it->get_data(); }
+ pointer operator->() const { return pointer(&this->m_it->get_data()); }
//Increment / Decrement
iterator& operator++()
@@ -495,25 +517,59 @@
{ return iterator(this->icont().begin()); }
const_iterator begin() const
- { return const_iterator(this->non_const_icont().begin()); }
+ { return this->cbegin(); }
iterator end()
{ return iterator(this->icont().end()); }
const_iterator end() const
- { return const_iterator(this->non_const_icont().end()); }
+ { return this->cend(); }
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
- { return const_reverse_iterator(end()); }
+ { return this->crbegin(); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
- { return const_reverse_iterator(begin()); }
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return const_iterator(this->non_const_icont().begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return const_iterator(this->non_const_icont().end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return const_reverse_iterator(cbegin()); }
bool empty() const
{ return !this->size(); }
@@ -621,6 +677,113 @@
}
#endif
+ private:
+ iterator emplace_unique_impl(NodePtr p)
+ {
+ value_type &v = p->get_data();
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(KeyOfValue()(v), data);
+ if(!ret.second){
+ Destroyer(this->node_alloc())(p);
+ return ret.first;
+ }
+ return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
+ }
+
+ iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p)
+ {
+ value_type &v = p->get_data();
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(hint, KeyOfValue()(v), data);
+ if(!ret.second){
+ Destroyer(this->node_alloc())(p);
+ return ret.first;
+ }
+ return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
+ }
+
+ public:
+
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template <class... Args>
+ iterator emplace_unique(Args&&... args)
+ { return this->emplace_unique_impl(AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
+
+ template <class... Args>
+ iterator emplace_hint_unique(const_iterator hint, Args&&... args)
+ { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(detail::forward_impl<Args>(args)...)); }
+
+ template <class... Args>
+ iterator emplace_equal(Args&&... args)
+ {
+ NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
+ return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ }
+
+ template <class... Args>
+ iterator emplace_hint_equal(const_iterator hint, Args&&... args)
+ {
+ NodePtr p(AllocHolder::create_node(detail::forward_impl<Args>(args)...));
+ return iterator(this->icont().insert_equal(hint.get(), *p));
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace_unique()
+ { return this->emplace_unique_impl(AllocHolder::create_node()); }
+
+ iterator emplace_hint_unique(const_iterator hint)
+ { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node()); }
+
+ iterator emplace_equal()
+ {
+ NodePtr p(AllocHolder::create_node());
+ return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ }
+
+ iterator emplace_hint_equal(const_iterator hint)
+ {
+ NodePtr p(AllocHolder::create_node());
+ return iterator(this->icont().insert_equal(hint.get(), *p));
+ }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return this->emplace_unique_impl \
+ (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint_unique(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return this->emplace_unique_hint_impl \
+ (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint_equal(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ return iterator(this->icont().insert_equal(hint.get(), *p)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
iterator insert_unique(const_iterator hint, const value_type& v)
{
insert_commit_data data;
@@ -663,7 +826,7 @@
if(this->empty()){
//Insert with end hint, to achieve linear
//complexity if [first, last) is ordered
- iterator end(this->end());
+ const_iterator end(this->end());
for( ; first != last; ++first)
this->insert_unique(end, *first);
}
@@ -722,7 +885,7 @@
{
//Insert with end hint, to achieve linear
//complexity if [first, last) is ordered
- iterator end(this->end());
+ const_iterator end(this->cend());
for( ; first != last; ++first)
this->insert_equal(end, *first);
}
@@ -815,7 +978,6 @@
class insertion_functor
{
Icont &icont_;
- typename Icont::iterator pos_;
public:
insertion_functor(Icont &icont)
@@ -823,7 +985,7 @@
{}
void operator()(Node &n)
- { this->icont_.insert_equal(this->icont_.end(), n); }
+ { this->icont_.insert_equal(this->icont_.cend(), n); }
};
Modified: trunk/boost/interprocess/containers/flat_map.hpp
==============================================================================
--- trunk/boost/interprocess/containers/flat_map.hpp (original)
+++ trunk/boost/interprocess/containers/flat_map.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -77,7 +77,7 @@
Pred,
Alloc> tree_t;
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ //#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
//This is the real tree stored here. It's based on a movable pair
typedef detail::flat_tree<Key,
detail::pair<Key, T>,
@@ -85,10 +85,11 @@
Pred,
typename Alloc::template
rebind<detail::pair<Key, T> >::other> impl_tree_t;
+/*
#else
typedef tree_t impl_tree_t;
#endif
-
+*/
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -106,20 +107,17 @@
typedef detail::moved_object<impl_value_type> impl_moved_value_type;
#endif
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ //#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class D, class S>
static D &force(const S &s)
- { return *((D*)(void*)(const void*)(&s)); }
- #else
- //For rvalue-aware compilers, just forward
- template<class Type>
- static const Type &force(const Type &t)
- { return t; }
-
- template<class Type>
- static Type &force(Type &t)
- { return t; }
- #endif
+ { return *const_cast<D*>(reinterpret_cast<const D*>(&s)); }
+
+ template<class D, class S>
+ static D force_copy(S s)
+ {
+ value_type *vp = reinterpret_cast<value_type *>(&*s);
+ return D(vp);
+ }
/// @endcond
@@ -235,7 +233,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator begin()
- { return force<iterator>(m_flat_tree.begin()); }
+ { return force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
@@ -245,13 +243,21 @@
const_iterator begin() const
{ return force<const_iterator>(m_flat_tree.begin()); }
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return force<const_iterator>(m_flat_tree.cbegin()); }
+
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
iterator end()
- { return force<iterator>(m_flat_tree.end()); }
+ { return force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
@@ -261,6 +267,14 @@
const_iterator end() const
{ return force<const_iterator>(m_flat_tree.end()); }
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return force<const_iterator>(m_flat_tree.cend()); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
//!
@@ -279,6 +293,15 @@
const_reverse_iterator rbegin() const
{ return force<const_reverse_iterator>(m_flat_tree.rbegin()); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return force<const_reverse_iterator>(m_flat_tree.crbegin()); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
//!
@@ -297,6 +320,15 @@
const_reverse_iterator rend() const
{ return force<const_reverse_iterator>(m_flat_tree.rend()); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return force<const_reverse_iterator>(m_flat_tree.crend()); }
+
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
@@ -425,7 +457,8 @@
m_flat_tree.insert_unique(force<impl_moved_value_type>(x))); }
#else
std::pair<iterator,bool> insert(value_type &&x)
- { return m_flat_tree.insert_unique(detail::move_impl(x)); }
+ { return force<std::pair<iterator,bool> >(
+ m_flat_tree.insert_unique(detail::move_impl(force<impl_value_type>(x)))); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
@@ -439,9 +472,9 @@
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
- iterator insert(iterator position, const value_type& x)
- { return force<iterator>(
- m_flat_tree.insert_unique(force<impl_iterator>(position), force<impl_value_type>(x))); }
+ iterator insert(const_iterator position, const value_type& x)
+ { return force_copy<iterator>(
+ m_flat_tree.insert_unique(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -453,12 +486,13 @@
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<value_type>& x)
- { return force<iterator>(
- m_flat_tree.insert_unique(force<impl_iterator>(position), force<impl_moved_value_type>(x))); }
+ iterator insert(const_iterator position, const detail::moved_object<value_type>& x)
+ { return force_copy<iterator>(
+ m_flat_tree.insert_unique(force<impl_const_iterator>(position), force<impl_moved_value_type>(x))); }
#else
- iterator insert(iterator position, value_type &&x)
- { return m_flat_tree.insert_unique(position, detail::move_impl(x)); }
+ iterator insert(const_iterator position, value_type &&x)
+ { return force_copy<iterator>(
+ m_flat_tree.insert_unique(force<impl_const_iterator>(position), detail::move_impl(force<impl_value_type>(x)))); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
@@ -472,7 +506,70 @@
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_flat_tree.insert_unique(first, last); }
+ { m_flat_tree.insert_unique(first, last); }
+
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... if and only if there is no element in the container
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return force_copy<iterator>(m_flat_tree.emplace_unique(detail::forward_impl<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint), detail::forward_impl<Args>(args)...)); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return force_copy<iterator>(m_flat_tree.emplace_unique()); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return force_copy<iterator>(m_flat_tree.emplace_hint_unique(force<impl_const_iterator>(hint))); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return force_copy<iterator>(m_flat_tree.emplace_unique \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return force_copy<iterator>(m_flat_tree.emplace_hint_unique \
+ (force<impl_const_iterator>(hint), \
+ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
//! <b>Effects</b>: Erases the element pointed to by position.
//!
@@ -485,7 +582,7 @@
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
iterator erase(const_iterator position)
- { return force<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
+ { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
//!
@@ -505,7 +602,7 @@
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
iterator erase(const_iterator first, const_iterator last)
- { return force<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
+ { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
@@ -529,7 +626,7 @@
//!
//! <b>Complexity</b>: Logarithmic.
iterator find(const key_type& x)
- { return force<iterator>(m_flat_tree.find(x)); }
+ { return force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: A const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
@@ -549,7 +646,7 @@
//!
//! <b>Complexity</b>: Logarithmic
iterator lower_bound(const key_type& x)
- { return force<iterator>(m_flat_tree.lower_bound(x)); }
+ { return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than k, or a.end() if such an element is not found.
@@ -563,7 +660,7 @@
//!
//! <b>Complexity</b>: Logarithmic
iterator upper_bound(const key_type& x)
- { return force<iterator>(m_flat_tree.upper_bound(x)); }
+ { return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key not
//! less than x, or end() if such an element is not found.
@@ -725,7 +822,7 @@
detail::select1st< std::pair<Key, T> >,
Pred,
Alloc> tree_t;
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ //#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
//This is the real tree stored here. It's based on a movable pair
typedef detail::flat_tree<Key,
detail::pair<Key, T>,
@@ -733,10 +830,11 @@
Pred,
typename Alloc::template
rebind<detail::pair<Key, T> >::other> impl_tree_t;
+/*
#else
typedef tree_t impl_tree_t;
#endif
-
+*/
impl_tree_t m_flat_tree; // flat tree representing flat_map
typedef typename impl_tree_t::value_type impl_value_type;
@@ -754,20 +852,17 @@
typedef detail::moved_object<impl_value_type> impl_moved_value_type;
#endif
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ //#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template<class D, class S>
static D &force(const S &s)
{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); }
- #else
- //For rvalue-aware compilers, just forward
- template<class Type>
- static const Type &force(const Type &t)
- { return t; }
-
- template<class Type>
- static Type &force(Type &t)
- { return t; }
- #endif
+
+ template<class D, class S>
+ static D force_copy(S s)
+ {
+ value_type *vp = reinterpret_cast<value_type *>(&*s);
+ return D(vp);
+ }
/// @endcond
public:
@@ -882,7 +977,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator begin()
- { return force<iterator>(m_flat_tree.begin()); }
+ { return force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
@@ -898,7 +993,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator end()
- { return force<iterator>(m_flat_tree.end()); }
+ { return force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
@@ -999,7 +1094,7 @@
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
iterator insert(const value_type& x)
- { return force<iterator>(m_flat_tree.insert_equal(force<impl_value_type>(x))); }
+ { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
//! the iterator pointing to the newly inserted element.
@@ -1010,10 +1105,10 @@
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
iterator insert(const detail::moved_object<value_type>& x)
- { return force<iterator>(m_flat_tree.insert_equal(force<impl_moved_value_type>(x))); }
+ { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_moved_value_type>(x))); }
#else
iterator insert(value_type &&x)
- { return m_flat_tree.insert_equal(detail::move_impl(x)); }
+ { return force_copy<iterator>(m_flat_tree.insert_equal(detail::move_impl(x))); }
#endif
//! <b>Effects</b>: Inserts a copy of x in the container.
@@ -1027,8 +1122,8 @@
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
- iterator insert(iterator position, const value_type& x)
- { return force<iterator>(m_flat_tree.insert_equal(force<impl_iterator>(position), force<impl_value_type>(x))); }
+ iterator insert(const_iterator position, const value_type& x)
+ { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_const_iterator>(position), force<impl_value_type>(x))); }
//! <b>Effects</b>: Inserts a value move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
@@ -1042,11 +1137,11 @@
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<value_type>& x)
- { return force<iterator>(m_flat_tree.insert_equal(force<impl_iterator>(position), force<impl_moved_value_type>(x))); }
+ iterator insert(const_iterator position, const detail::moved_object<value_type>& x)
+ { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_const_iterator>(position), force<impl_moved_value_type>(x))); }
#else
- iterator insert(iterator position, value_type &&x)
- { return m_flat_tree.insert_equal(force<impl_iterator>(position), detail::move_impl(x)); }
+ iterator insert(const_iterator position, value_type &&x)
+ { return force_copy<iterator>(m_flat_tree.insert_equal(force<impl_const_iterator>(position), detail::move_impl(x))); }
#endif
//! <b>Requires</b>: i, j are not iterators into *this.
@@ -1061,6 +1156,68 @@
void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return force_copy<iterator>(m_flat_tree.emplace_equal(detail::forward_impl<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ {
+ return force_copy<iterator>(m_flat_tree.emplace_hint_equal
+ (force<impl_const_iterator>(hint), detail::forward_impl<Args>(args)...));
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return force_copy<iterator>(m_flat_tree.emplace_equal()); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return force_copy<iterator>(m_flat_tree.emplace_hint_equal(force<impl_const_iterator>(hint))); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return force_copy<iterator>(m_flat_tree.emplace_equal \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return force_copy<iterator>(m_flat_tree.emplace_hint_equal \
+ (force<impl_const_iterator>(hint), \
+ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _))); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by position.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
@@ -1072,7 +1229,7 @@
//! <b>Note</b>: Invalidates elements with keys
//! not less than the erased element.
iterator erase(const_iterator position)
- { return force<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
+ { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(position))); }
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
//!
@@ -1092,7 +1249,7 @@
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
iterator erase(const_iterator first, const_iterator last)
- { return force<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
+ { return force_copy<iterator>(m_flat_tree.erase(force<impl_const_iterator>(first), force<impl_const_iterator>(last))); }
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
@@ -1116,7 +1273,7 @@
//!
//! <b>Complexity</b>: Logarithmic.
iterator find(const key_type& x)
- { return force<iterator>(m_flat_tree.find(x)); }
+ { return force_copy<iterator>(m_flat_tree.find(x)); }
//! <b>Returns</b>: An const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
@@ -1136,7 +1293,7 @@
//!
//! <b>Complexity</b>: Logarithmic
iterator lower_bound(const key_type& x)
- {return force<iterator>(m_flat_tree.lower_bound(x)); }
+ {return force_copy<iterator>(m_flat_tree.lower_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than k, or a.end() if such an element is not found.
@@ -1150,7 +1307,7 @@
//!
//! <b>Complexity</b>: Logarithmic
iterator upper_bound(const key_type& x)
- {return force<iterator>(m_flat_tree.upper_bound(x)); }
+ {return force_copy<iterator>(m_flat_tree.upper_bound(x)); }
//! <b>Returns</b>: A const iterator pointing to the first element with key
//! not less than x, or end() if such an element is not found.
@@ -1163,14 +1320,14 @@
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
- { return force<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+ { return force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator>
equal_range(const key_type& x) const
- { return force<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+ { return force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
Modified: trunk/boost/interprocess/containers/flat_set.hpp
==============================================================================
--- trunk/boost/interprocess/containers/flat_set.hpp (original)
+++ trunk/boost/interprocess/containers/flat_set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -185,6 +185,14 @@
const_iterator begin() const
{ return m_flat_tree.begin(); }
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return m_flat_tree.cbegin(); }
+
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
@@ -201,6 +209,14 @@
const_iterator end() const
{ return m_flat_tree.end(); }
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return m_flat_tree.cend(); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
//!
@@ -219,6 +235,15 @@
const_reverse_iterator rbegin() const
{ return m_flat_tree.rbegin(); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return m_flat_tree.crbegin(); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
//!
@@ -237,6 +262,15 @@
const_reverse_iterator rend() const
{ return m_flat_tree.rend(); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return m_flat_tree.crend(); }
+
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
@@ -328,7 +362,7 @@
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
- iterator insert(iterator position, const value_type& x)
+ iterator insert(const_iterator position, const value_type& x)
{ return m_flat_tree.insert_unique(position, x); }
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
@@ -341,10 +375,10 @@
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<value_type>& x)
+ iterator insert(const_iterator position, const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_unique(position, x); }
#else
- iterator insert(iterator position, value_type && x)
+ iterator insert(const_iterator position, value_type && x)
{ return m_flat_tree.insert_unique(position, detail::move_impl(x)); }
#endif
@@ -361,6 +395,62 @@
void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_unique(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... if and only if there is no element in the container
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_flat_tree.emplace_unique(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_flat_tree.emplace_hint_unique(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_flat_tree.emplace_unique(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_flat_tree.emplace_hint_unique(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_flat_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); }\
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by position.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
@@ -704,6 +794,14 @@
const_iterator begin() const
{ return m_flat_tree.begin(); }
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return m_flat_tree.cbegin(); }
+
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
@@ -720,6 +818,14 @@
const_iterator end() const
{ return m_flat_tree.end(); }
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return m_flat_tree.cend(); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
//!
@@ -738,6 +844,15 @@
const_reverse_iterator rbegin() const
{ return m_flat_tree.rbegin(); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return m_flat_tree.crbegin(); }
+
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
//!
@@ -756,6 +871,15 @@
const_reverse_iterator rend() const
{ return m_flat_tree.rend(); }
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return m_flat_tree.crend(); }
+
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
@@ -838,7 +962,7 @@
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
- iterator insert(iterator position, const value_type& x)
+ iterator insert(const_iterator position, const value_type& x)
{ return m_flat_tree.insert_equal(position, x); }
//! <b>Effects</b>: Inserts a new value move constructed from x in the container.
@@ -852,10 +976,10 @@
//!
//! <b>Note</b>: If an element it's inserted it might invalidate elements.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<value_type>& x)
+ iterator insert(const_iterator position, const detail::moved_object<value_type>& x)
{ return m_flat_tree.insert_equal(position, x); }
#else
- iterator insert(iterator position, value_type && x)
+ iterator insert(const_iterator position, value_type && x)
{ return m_flat_tree.insert_equal(position, detail::move_impl(x)); }
#endif
@@ -871,6 +995,57 @@
void insert(InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_flat_tree.emplace_equal(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element it's inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_flat_tree.emplace_hint_equal(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_flat_tree.emplace_equal(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_flat_tree.emplace_hint_equal(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_flat_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_flat_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by position.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
Modified: trunk/boost/interprocess/containers/list.hpp
==============================================================================
--- trunk/boost/interprocess/containers/list.hpp (original)
+++ trunk/boost/interprocess/containers/list.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -49,7 +49,6 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <boost/interprocess/detail/move.hpp>
@@ -60,6 +59,11 @@
#include <boost/intrusive/list.hpp>
#include <boost/interprocess/containers/detail/node_alloc_holder.hpp>
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+//Preprocessor library to emulate perfect forwarding
+#include <boost/interprocess/detail/preprocessor.hpp>
+#endif
+
#include <iterator>
#include <utility>
#include <memory>
@@ -73,29 +77,40 @@
/// @cond
namespace detail {
+template<class VoidPointer>
+struct list_hook
+{
+ typedef typename bi::make_list_base_hook
+ <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type type;
+};
+
template <class T, class VoidPointer>
struct list_node
- : public bi::make_list_base_hook
- <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type
+ : public list_hook<VoidPointer>::type
{
- typedef typename bi::make_list_base_hook
- <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type hook_type;
+
+ #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
list_node()
: m_data()
{}
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template<class Convertible>
- list_node(const Convertible &conv)
- : m_data(conv)
- {}
- #else
- template<class Convertible>
- list_node(Convertible &&conv)
- : m_data(detail::forward_impl<Convertible>(conv))
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ list_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ : m_data(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
+ {} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #else //#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class ...Args>
+ list_node(Args &&...args)
+ : m_data(detail::forward_impl<Args>(args)...)
{}
- #endif
+ #endif//#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
T m_data;
};
@@ -110,7 +125,7 @@
<value_type, void_pointer> node_type;
typedef typename bi::make_list
< node_type
- , bi::base_hook<typename node_type::hook_type>
+ , bi::base_hook<typename list_hook<void_pointer>::type>
, bi::constant_time_size<true>
, bi::size_type<typename A::size_type>
>::type container_type;
@@ -335,7 +350,7 @@
//! <b>Complexity</b>: Linear to n.
list(size_type n, const T& value = T(), const A& a = A())
: AllocHolder(a)
- { this->insert(begin(), n, value); }
+ { this->insert(this->cbegin(), n, value); }
//! <b>Effects</b>: Copy constructs a list.
//!
@@ -346,7 +361,7 @@
//! <b>Complexity</b>: Linear to the elements x contains.
list(const list& x)
: AllocHolder(x)
- { this->insert(begin(), x.begin(), x.end()); }
+ { this->insert(this->cbegin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
//!
@@ -373,7 +388,7 @@
template <class InpIt>
list(InpIt first, InpIt last, const A &a = A())
: AllocHolder(a)
- { insert(begin(), first, last); }
+ { this->insert(this->cbegin(), first, last); }
//! <b>Effects</b>: Destroys the list. All stored values are destroyed
//! and used memory is deallocated.
@@ -420,7 +435,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
- { return const_iterator(this->non_const_icont().begin()); }
+ { return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
//!
@@ -436,7 +451,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
- { return const_iterator(this->non_const_icont().end()); }
+ { return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed list.
@@ -454,7 +469,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin() const
- { return const_reverse_iterator(end()); }
+ { return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed list.
@@ -472,7 +487,41 @@
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
- { return const_reverse_iterator(begin()); }
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return const_iterator(this->non_const_icont().begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return const_iterator(this->non_const_icont().end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(this->cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return const_reverse_iterator(this->cbegin()); }
//! <b>Effects</b>: Returns true if the list contains no elements.
//!
@@ -505,7 +554,7 @@
//!
//! <b>Complexity</b>: Amortized constant time.
void push_front(const T& x)
- { this->insert(this->begin(), x); }
+ { this->insert(this->cbegin(), x); }
//! <b>Effects</b>: Constructs a new element in the beginning of the list
//! and moves the resources of t to this new element.
@@ -515,10 +564,10 @@
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_front(const detail::moved_object<T>& x)
- { this->insert(this->begin(), x); }
+ { this->insert(this->cbegin(), x); }
#else
void push_front(T &&x)
- { this->insert(this->begin(), detail::move_impl(x)); }
+ { this->insert(this->cbegin(), detail::move_impl(x)); }
#endif
//! <b>Effects</b>: Removes the last element from the list.
@@ -527,7 +576,7 @@
//!
//! <b>Complexity</b>: Amortized constant time.
void push_back (const T& x)
- { this->insert(this->end(), x); }
+ { this->insert(this->cend(), x); }
//! <b>Effects</b>: Removes the first element from the list.
//!
@@ -536,10 +585,10 @@
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back (const detail::moved_object<T>& x)
- { this->insert(this->end(), x); }
+ { this->insert(this->cend(), x); }
#else
void push_back (T &&x)
- { this->insert(this->end(), detail::move_impl(x)); }
+ { this->insert(this->cend(), detail::move_impl(x)); }
#endif
//! <b>Effects</b>: Removes the first element from the list.
@@ -548,7 +597,7 @@
//!
//! <b>Complexity</b>: Amortized constant time.
void pop_front()
- { this->erase(this->begin()); }
+ { this->erase(this->cbegin()); }
//! <b>Effects</b>: Removes the last element from the list.
//!
@@ -556,7 +605,7 @@
//!
//! <b>Complexity</b>: Amortized constant time.
void pop_back()
- { iterator tmp = this->end(); this->erase(--tmp); }
+ { const_iterator tmp = this->cend(); this->erase(--tmp); }
//! <b>Requires</b>: !empty()
//!
@@ -610,7 +659,7 @@
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size, const T& x)
{
- iterator iend = this->end();
+ const_iterator iend = this->cend();
size_type len = this->size();
if(len > new_size){
@@ -618,7 +667,7 @@
while(to_erase--){
--iend;
}
- this->erase(iend, this->end());
+ this->erase(iend, this->cend());
}
else{
this->priv_create_and_insert_nodes(iend, new_size - len, x);
@@ -633,12 +682,12 @@
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size)
{
- iterator iend = this->end();
+ const_iterator iend = this->end();
size_type len = this->size();
if(len > new_size){
size_type to_erase = len - new_size;
- iterator ifirst;
+ const_iterator ifirst;
if(to_erase < len/2u){
ifirst = iend;
while(to_erase--){
@@ -655,7 +704,7 @@
this->erase(ifirst, iend);
}
else{
- this->priv_create_and_insert_nodes(this->end(), new_size - len);
+ this->priv_create_and_insert_nodes(this->cend(), new_size - len);
}
}
@@ -726,7 +775,7 @@
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- void insert(iterator p, size_type n, const T& x)
+ void insert(const_iterator p, size_type n, const T& x)
{ this->priv_create_and_insert_nodes(p, n, x); }
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -738,7 +787,7 @@
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InpIt>
- void insert(iterator p, InpIt first, InpIt last)
+ void insert(const_iterator p, InpIt first, InpIt last)
{
const bool aux_boolean = detail::is_convertible<InpIt, std::size_t>::value;
typedef detail::bool_<aux_boolean> Result;
@@ -752,7 +801,7 @@
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time.
- iterator insert(iterator p, const T& x)
+ iterator insert(const_iterator p, const T& x)
{
NodePtr tmp = AllocHolder::create_node(x);
return iterator(this->icont().insert(p.get(), *tmp));
@@ -766,19 +815,109 @@
//!
//! <b>Complexity</b>: Amortized constant time.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator p, const detail::moved_object<T>& x)
+ iterator insert(const_iterator p, const detail::moved_object<T>& x)
{
NodePtr tmp = AllocHolder::create_node(x);
return iterator(this->icont().insert(p.get(), *tmp));
}
#else
- iterator insert(iterator p, T &&x)
+ iterator insert(const_iterator p, T &&x)
{
NodePtr tmp = AllocHolder::create_node(detail::move_impl(x));
return iterator(this->icont().insert(p.get(), *tmp));
}
#endif
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the list.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ void emplace_back(Args&&... args)
+ {
+ this->emplace(this->cend(), detail::forward_impl<Args>(args)...);
+ }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the beginning of the list.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ void emplace_front(Args&&... args)
+ {
+ this->emplace(this->cbegin(), detail::forward_impl<Args>(args)...);
+ }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ iterator emplace(const_iterator p, Args&&... args)
+ {
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
+ new ((void*)detail::get_pointer(d.get())) Node(detail::forward_impl<Args>(args)...);
+ NodePtr node = d.get();
+ d.release();
+ return iterator(this->icont().insert(p.get(), *node));
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //0 args
+ void emplace_back()
+ { this->emplace(this->cend()); }
+
+ void emplace_front()
+ { this->emplace(this->cbegin()); }
+
+ iterator emplace(const_iterator p)
+ {
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
+ new ((void*)detail::get_pointer(d.get())) Node();
+ NodePtr node = d.get();
+ d.release();
+ return iterator(this->icont().insert(p.get(), *node));
+ }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ this->emplace(this->cend(), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_front(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { this->emplace(this->cbegin(), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _));} \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(const_iterator p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); \
+ new ((void*)detail::get_pointer(d.get())) \
+ Node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ NodePtr node = d.get(); \
+ d.release(); \
+ return iterator(this->icont().insert(p.get(), *node)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Erases the element at p p.
@@ -786,7 +925,7 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
- iterator erase(iterator p)
+ iterator erase(const_iterator p)
{ return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -796,7 +935,7 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the distance between first and last.
- iterator erase(iterator first, iterator last)
+ iterator erase(const_iterator first, const_iterator last)
{ return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); }
//! <b>Effects</b>: Assigns the n copies of val to *this.
@@ -861,7 +1000,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, ThisType &x, iterator i)
+ void splice(const_iterator p, ThisType &x, const_iterator i)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice(p.get(), x.icont(), i.get());
@@ -871,7 +1010,7 @@
}
}
-// void splice(iterator p, const detail::moved_object<ThisType> &x, iterator i)
+// void splice(const_iterator p, const detail::moved_object<ThisType> &x, const_iterator i)
// { this->splice(p, x.get(), i); }
//! <b>Requires</b>: p must point to an element contained
@@ -887,7 +1026,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, ThisType &x, iterator first, iterator last)
+ void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice(p.get(), x.icont(), first.get(), last.get());
@@ -897,7 +1036,7 @@
}
}
-// void splice(iterator p, detail::moved_object<ThisType> &x, iterator first, iterator last)
+// void splice(const_iterator p, detail::moved_object<ThisType> &x, const_iterator first, const_iterator last)
// { return this->splice(p, x.get(), first, last); }
//! <b>Requires</b>: p must point to an element contained
@@ -914,7 +1053,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, ThisType &x, iterator first, iterator last, size_type n)
+ void splice(const_iterator p, ThisType &x, const_iterator first, const_iterator last, size_type n)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n);
@@ -924,7 +1063,7 @@
}
}
-// void splice(iterator p, detail::moved_object<ThisType> &x, iterator first, iterator last, size_type n)
+// void splice(const_iterator p, detail::moved_object<ThisType> &x, const_iterator first, const_iterator last, size_type n)
// { return this->splice(p, x.get(), first, last, n); }
//! <b>Effects</b>: Reverses the order of elements in the list.
@@ -1128,10 +1267,10 @@
class insertion_functor
{
Icont &icont_;
- typename Icont::iterator pos_;
+ typename Icont::const_iterator pos_;
public:
- insertion_functor(Icont &icont, typename Icont::iterator pos)
+ insertion_functor(Icont &icont, typename Icont::const_iterator pos)
: icont_(icont), pos_(pos)
{}
@@ -1165,13 +1304,13 @@
//Dispatch to detect iterator range or integer overloads
template <class InputIter>
- void priv_insert_dispatch(iterator p,
+ void priv_insert_dispatch(const_iterator p,
InputIter first, InputIter last,
detail::false_)
{ this->priv_create_and_insert_nodes(p, first, last); }
template<class Integer>
- void priv_insert_dispatch(iterator p, Integer n, Integer x, detail::true_)
+ void priv_insert_dispatch(const_iterator p, Integer n, Integer x, detail::true_)
{ this->insert(p, (size_type)n, x); }
void priv_fill_assign(size_type n, const T& val)
@@ -1181,10 +1320,10 @@
for ( ; i != iend && n > 0; ++i, --n)
*i = val;
if (n > 0){
- this->priv_create_and_insert_nodes(this->end(), n, val);
+ this->priv_create_and_insert_nodes(this->cend(), n, val);
}
else{
- this->erase(i, end());
+ this->erase(i, cend());
}
}
@@ -1193,8 +1332,7 @@
{ this->priv_fill_assign((size_type) n, (T) val); }
template <class InputIter>
- void priv_assign_dispatch(InputIter first2, InputIter last2,
- detail::false_)
+ void priv_assign_dispatch(InputIter first2, InputIter last2, detail::false_)
{
iterator first1 = this->begin();
iterator last1 = this->end();
Modified: trunk/boost/interprocess/containers/map.hpp
==============================================================================
--- trunk/boost/interprocess/containers/map.hpp (original)
+++ trunk/boost/interprocess/containers/map.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -530,6 +530,58 @@
void insert(InputIterator first, InputIterator last)
{ m_tree.insert_unique(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with an equivalent key.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_tree.emplace_unique(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with an equivalent key.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_tree.emplace_hint_unique(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_tree.emplace_unique(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_tree.emplace_hint_unique(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _));}\
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by position.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
@@ -1056,6 +1108,56 @@
void insert(InputIterator first, InputIterator last)
{ m_tree.insert_equal(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_tree.emplace_equal(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_tree.emplace_hint_equal(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_tree.emplace_equal(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_tree.emplace_hint_equal(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); }\
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by position.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
Modified: trunk/boost/interprocess/containers/set.hpp
==============================================================================
--- trunk/boost/interprocess/containers/set.hpp (original)
+++ trunk/boost/interprocess/containers/set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -59,6 +59,9 @@
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/interprocess/containers/detail/tree.hpp>
#include <boost/interprocess/detail/move.hpp>
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#endif
namespace boost { namespace interprocess {
@@ -263,6 +266,40 @@
const_reverse_iterator rend() const
{ return m_tree.rend(); }
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return m_tree.cbegin(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return m_tree.cend(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return m_tree.crbegin(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return m_tree.crend(); }
+
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
@@ -373,6 +410,57 @@
void insert(InputIterator first, InputIterator last)
{ m_tree.insert_unique(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... if and only if there is
+ //! no element in the container with equivalent value.
+ //! and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_tree.emplace_unique(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... if and only if there is
+ //! no element in the container with equivalent value.
+ //! p is a hint pointing to where the insert
+ //! should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_tree.emplace_hint_unique(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_tree.emplace_unique(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_tree.emplace_hint_unique(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_hint_unique(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _));}\
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by p.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
@@ -752,6 +840,40 @@
const_reverse_iterator rend() const
{ return m_tree.rend(); }
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return m_tree.cbegin(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return m_tree.cend(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const
+ { return m_tree.crbegin(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
+ { return m_tree.crend(); }
+
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
@@ -857,6 +979,51 @@
void insert(InputIterator first, InputIterator last)
{ m_tree.insert_equal(first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return m_tree.emplace_equal(detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)...
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ { return m_tree.emplace_hint_equal(hint, detail::forward_impl<Args>(args)...); }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ iterator emplace()
+ { return m_tree.emplace_equal(); }
+
+ iterator emplace_hint(const_iterator hint)
+ { return m_tree.emplace_hint_equal(hint); }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_hint(const_iterator hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { return m_tree.emplace_hint_equal(hint, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); }\
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element pointed to by p.
//!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately
Modified: trunk/boost/interprocess/containers/slist.hpp
==============================================================================
--- trunk/boost/interprocess/containers/slist.hpp (original)
+++ trunk/boost/interprocess/containers/slist.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -59,6 +59,12 @@
#include <boost/interprocess/containers/detail/node_alloc_holder.hpp>
#include <boost/intrusive/slist.hpp>
+
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+//Preprocessor library to emulate perfect forwarding
+#include <boost/interprocess/detail/preprocessor.hpp>
+#endif
+
#include <iterator>
#include <utility>
#include <memory>
@@ -67,28 +73,43 @@
namespace boost{ namespace interprocess{
-namespace detail {
/// @cond
+
+namespace detail {
+
+template<class VoidPointer>
+struct slist_hook
+{
+ typedef typename bi::make_slist_base_hook
+ <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type type;
+};
+
template <class T, class VoidPointer>
struct slist_node
- : public bi::make_slist_base_hook
- <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type
+ : public slist_hook<VoidPointer>::type
{
- typedef typename bi::make_slist_base_hook
- <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type hook_type;
+ #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
slist_node()
: m_data()
{}
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template<class Convertible>
- slist_node(const Convertible &value)
- : m_data(value){}
- #else
- template<class Convertible>
- slist_node(Convertible &&value)
- : m_data(detail::forward_impl<Convertible>(value)){}
- #endif
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ slist_node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ : m_data(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
+ {} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #else //#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class ...Args>
+ slist_node(Args &&...args)
+ : m_data(detail::forward_impl<Args>(args)...)
+ {}
+ #endif//#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
T m_data;
};
@@ -104,16 +125,17 @@
typedef typename bi::make_slist
<node_type
- ,bi::base_hook<typename node_type::hook_type>
+ ,bi::base_hook<typename slist_hook<void_pointer>::type>
,bi::constant_time_size<true>
,bi::size_type<typename A::size_type>
>::type container_type;
typedef container_type type ;
};
-/// @endcond
} //namespace detail {
+/// @endcond
+
//! An slist is a singly linked list: a list where each element is linked to the next
//! element, but not to the previous element. That is, it is a Sequence that
//! supports forward but not backward traversal, and (amortized) constant time
@@ -480,7 +502,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const
- { return const_iterator(this->non_const_icont().begin()); }
+ { return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
//!
@@ -496,7 +518,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
- { return const_iterator(this->non_const_icont().end()); }
+ { return this->cend(); }
//! <b>Effects</b>: Returns a non-dereferenceable iterator that,
//! when incremented, yields begin(). This iterator may be used
@@ -516,6 +538,32 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator before_begin() const
+ { return this->cbefore_begin(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return const_iterator(this->non_const_icont().begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return const_iterator(this->non_const_icont().end()); }
+
+ //! <b>Effects</b>: Returns a non-dereferenceable const_iterator
+ //! that, when incremented, yields begin(). This iterator may be used
+ //! as the argument toinsert_after, erase_after, etc.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbefore_begin() const
{ return const_iterator(end()); }
//! <b>Effects</b>: Returns the number of the elements contained in the list.
@@ -638,7 +686,7 @@
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
- iterator insert_after(iterator prev_pos, const value_type& x)
+ iterator insert_after(const_iterator prev_pos, const value_type& x)
{ return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(x))); }
//! <b>Requires</b>: prev_pos must be a valid iterator of *this.
@@ -655,10 +703,10 @@
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert_after(iterator prev_pos, const detail::moved_object<value_type>& x)
+ iterator insert_after(const_iterator prev_pos, const detail::moved_object<value_type>& x)
{ return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(x))); }
#else
- iterator insert_after(iterator prev_pos, value_type && x)
+ iterator insert_after(const_iterator prev_pos, value_type && x)
{ return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(detail::move_impl(x)))); }
#endif
@@ -672,7 +720,7 @@
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
- void insert_after(iterator prev_pos, size_type n, const value_type& x)
+ void insert_after(const_iterator prev_pos, size_type n, const value_type& x)
{ this->priv_create_and_insert_nodes(prev_pos, n, x); }
//! <b>Requires</b>: prev_pos must be a valid iterator of *this.
@@ -688,7 +736,7 @@
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
template <class InIter>
- void insert_after(iterator prev_pos, InIter first, InIter last)
+ void insert_after(const_iterator prev_pos, InIter first, InIter last)
{
const bool aux_boolean = detail::is_convertible<InIter, std::size_t>::value;
typedef detail::bool_<aux_boolean> Result;
@@ -702,7 +750,7 @@
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to the elements before p.
- iterator insert(iterator p, const value_type& x)
+ iterator insert(const_iterator p, const value_type& x)
{ return this->insert_after(previous(p), x); }
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -713,10 +761,10 @@
//!
//! <b>Complexity</b>: Linear to the elements before p.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator p, const detail::moved_object<value_type>& x)
+ iterator insert(const_iterator p, const detail::moved_object<value_type>& x)
{ return this->insert_after(previous(p), x); }
#else
- iterator insert(iterator p, value_type && x)
+ iterator insert(const_iterator p, value_type && x)
{ return this->insert_after(previous(p), detail::move_impl(x)); }
#endif
@@ -727,7 +775,7 @@
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n plus linear to the elements before p.
- void insert(iterator p, size_type n, const value_type& x)
+ void insert(const_iterator p, size_type n, const value_type& x)
{ return this->insert_after(previous(p), n, x); }
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -740,9 +788,101 @@
//! <b>Complexity</b>: Linear to std::distance [first, last) plus
//! linear to the elements before p.
template <class InIter>
- void insert(iterator p, InIter first, InIter last)
+ void insert(const_iterator p, InIter first, InIter last)
{ return this->insert_after(previous(p), first, last); }
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the front of the list
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template <class... Args>
+ void emplace_front(Args&&... args)
+ { this->emplace_after(this->cbefore_begin(), detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements before p
+ template <class... Args>
+ iterator emplace(const_iterator p, Args&&... args)
+ { return this->emplace_after(this->previous(p), detail::forward_impl<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... after prev
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ iterator emplace_after(const_iterator prev, Args&&... args)
+ {
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
+ new ((void*)detail::get_pointer(d.get())) Node(detail::forward_impl<Args>(args)...);
+ NodePtr node = d.get();
+ d.release();
+ return iterator(this->icont().insert_after(prev.get(), *node));
+ }
+
+ #else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //0 args
+ void emplace_front()
+ { this->emplace_after(this->cbefore_begin()); }
+
+ iterator emplace(const_iterator p)
+ { return this->emplace_after(this->previous(p)); }
+
+ iterator emplace_after(const_iterator prev)
+ {
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator());
+ new ((void*)detail::get_pointer(d.get())) Node();
+ NodePtr node = d.get();
+ d.release();
+ return iterator(this->icont().insert_after(prev.get(), *node));
+ }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_front(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ this->emplace \
+ (this->cbegin(), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace \
+ (const_iterator p, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ return this->emplace_after \
+ (this->previous(p), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace_after \
+ (const_iterator prev, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ typename AllocHolder::Deallocator d(AllocHolder::create_node_and_deallocator()); \
+ new ((void*)detail::get_pointer(d.get())) \
+ Node(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ NodePtr node = d.get(); \
+ d.release(); \
+ return iterator(this->icont().insert_after(prev.get(), *node)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//! <b>Effects</b>: Erases the element after the element pointed by prev_pos
//! of the list.
//!
@@ -754,7 +894,7 @@
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Does not invalidate iterators or references to non erased elements.
- iterator erase_after(iterator prev_pos)
+ iterator erase_after(const_iterator prev_pos)
{
return iterator(this->icont().erase_after_and_dispose(prev_pos.get(), Destroyer(this->node_alloc())));
}
@@ -770,7 +910,7 @@
//! <b>Complexity</b>: Linear to the number of erased elements.
//!
//! <b>Note</b>: Does not invalidate iterators or references to non erased elements.
- iterator erase_after(iterator before_first, iterator last)
+ iterator erase_after(const_iterator before_first, const_iterator last)
{
return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc())));
}
@@ -782,7 +922,7 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements before p.
- iterator erase(iterator p)
+ iterator erase(const_iterator p)
{ return iterator(this->erase_after(previous(p))); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -793,7 +933,7 @@
//!
//! <b>Complexity</b>: Linear to the distance between first and last plus
//! linear to the elements before first.
- iterator erase(iterator first, iterator last)
+ iterator erase(const_iterator first, const_iterator last)
{ return iterator(this->erase_after(previous(first), last)); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -810,9 +950,9 @@
cur = cur_next;
}
if (cur_next != end_n)
- this->erase_after(iterator(cur), iterator(end_n));
+ this->erase_after(const_iterator(cur), const_iterator(end_n));
else
- this->insert_after(iterator(cur), new_size, x);
+ this->insert_after(const_iterator(cur), new_size, x);
}
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -832,10 +972,10 @@
cur = cur_next;
}
if (cur_next != end_n){
- this->erase_after(iterator(cur), iterator(end_n));
+ this->erase_after(const_iterator(cur), const_iterator(end_n));
}
else{
- this->priv_create_and_insert_nodes(iterator(cur), new_size - len);
+ this->priv_create_and_insert_nodes(const_iterator(cur), new_size - len);
}
}
@@ -860,7 +1000,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist& x)
+ void splice_after(const_iterator prev_pos, slist& x)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice_after(prev_pos.get(), x.icont());
@@ -870,7 +1010,7 @@
}
}
- //void splice_after(iterator prev_pos, const detail::moved_object<slist>& x)
+ //void splice_after(const_iterator prev_pos, const detail::moved_object<slist>& x)
//{ this->splice_after(prev_pos, x.get()); }
// Moves the element that follows prev to *this, inserting it immediately
@@ -890,7 +1030,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist& x, iterator prev)
+ void splice_after(const_iterator prev_pos, slist& x, const_iterator prev)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice_after(prev_pos.get(), x.icont(), prev.get());
@@ -900,7 +1040,7 @@
}
}
- //void splice_after(iterator prev_pos, const detail::moved_object<slist>& x, iterator prev)
+ //void splice_after(const_iterator prev_pos, const detail::moved_object<slist>& x, iterator prev)
//{ return splice_after(prev_pos, x.get(), prev); }
// Moves the range [before_first + 1, before_last + 1) to *this,
@@ -921,8 +1061,8 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist& x,
- iterator before_first, iterator before_last)
+ void splice_after(const_iterator prev_pos, slist& x,
+ const_iterator before_first, const_iterator before_last)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
this->icont().splice_after
@@ -933,8 +1073,8 @@
}
}
- //void splice_after(iterator prev_pos, const detail::moved_object<slist>& x,
- // iterator before_first, iterator before_last)
+ //void splice_after(const_iterator prev_pos, const detail::moved_object<slist>& x,
+ // const_iterator before_first, const_iterator before_last)
//{ this->splice_after(prev_pos, x.get(), before_first, before_last); }
//! <b>Requires</b>: prev_pos must be a valid iterator of this.
@@ -952,8 +1092,8 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist& x,
- iterator before_first, iterator before_last,
+ void splice_after(const_iterator prev_pos, slist& x,
+ const_iterator before_first, const_iterator before_last,
size_type n)
{
if((NodeAlloc&)*this == (NodeAlloc&)x){
@@ -965,8 +1105,8 @@
}
}
- //void splice_after(iterator prev_pos, const detail::moved_object<slist>& x,
- // iterator before_first, iterator before_last, size_type n)
+ //void splice_after(const_iterator prev_pos, const detail::moved_object<slist>& x,
+ // const_iterator before_first, const_iterator before_last, size_type n)
//{ this->splice_after(prev_pos, x.get(), before_first, before_last, n); }
//! <b>Requires</b>: p must point to an element contained
@@ -982,10 +1122,10 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, slist& x)
+ void splice(const_iterator p, slist& x)
{ this->splice_after(this->previous(p), x); }
- //void splice(iterator p, const detail::moved_object<slist>& x)
+ //void splice(const_iterator p, const detail::moved_object<slist>& x)
//{ return this->splice(p, x.get()); }
//! <b>Requires</b>: p must point to an element contained
@@ -1002,10 +1142,10 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, slist& x, iterator i)
+ void splice(const_iterator p, slist& x, const_iterator i)
{ this->splice_after(previous(p), x, i); }
- //void splice(iterator p, const detail::moved_object<slist>& x, iterator i)
+ //void splice(const_iterator p, const detail::moved_object<slist>& x, const_iterator i)
//{ this->splice(p, x.get(), i); }
//! <b>Requires</b>: p must point to an element contained
@@ -1022,10 +1162,10 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, slist& x, iterator first, iterator last)
+ void splice(const_iterator p, slist& x, const_iterator first, const_iterator last)
{ this->splice_after(previous(p), x, previous(first), previous(last)); }
- //void splice(iterator p, const detail::moved_object<slist>& x, iterator first, iterator last)
+ //void splice(const_iterator p, const detail::moved_object<slist>& x, const_iterator first, const_iterator last)
//{ this->splice(p, x.get(), first, last); }
//! <b>Effects</b>: Reverses the order of elements in the list.
@@ -1205,10 +1345,10 @@
class insertion_functor
{
Icont &icont_;
- typename Icont::iterator prev_;
+ typename Icont::const_iterator prev_;
public:
- insertion_functor(Icont &icont, typename Icont::iterator prev)
+ insertion_functor(Icont &icont, typename Icont::const_iterator prev)
: icont_(icont), prev_(prev)
{}
@@ -1241,13 +1381,13 @@
//Dispatch to detect iterator range or integer overloads
template <class InputIter>
- void priv_insert_dispatch(iterator prev,
+ void priv_insert_dispatch(const_iterator prev,
InputIter first, InputIter last,
detail::false_)
{ this->priv_create_and_insert_nodes(prev, first, last); }
template<class Integer>
- void priv_insert_dispatch(iterator prev, Integer n, Integer x, detail::true_)
+ void priv_insert_dispatch(const_iterator prev, Integer n, Integer x, detail::true_)
{ this->priv_create_and_insert_nodes(prev, n, x); }
void priv_fill_assign(size_type n, const T& val)
@@ -1271,8 +1411,7 @@
{ this->priv_fill_assign((size_type) n, (T)val); }
template <class InpIt>
- void priv_assign_dispatch(InpIt first, InpIt last,
- detail::false_)
+ void priv_assign_dispatch(InpIt first, InpIt last, detail::false_)
{
iterator end_n(this->end());
iterator prev(this->before_begin());
@@ -1290,11 +1429,11 @@
}
template <class Int>
- void priv_insert_after_range_dispatch(iterator prev_pos, Int n, Int x, detail::true_)
+ void priv_insert_after_range_dispatch(const_iterator prev_pos, Int n, Int x, detail::true_)
{ this->priv_create_and_insert_nodes(prev_pos, n, x); }
template <class InIter>
- void priv_insert_after_range_dispatch(iterator prev_pos, InIter first, InIter last, detail::false_)
+ void priv_insert_after_range_dispatch(const_iterator prev_pos, InIter first, InIter last, detail::false_)
{ this->priv_create_and_insert_nodes(prev_pos, first, last); }
//Functors for member algorithm defaults
Modified: trunk/boost/interprocess/containers/string.hpp
==============================================================================
--- trunk/boost/interprocess/containers/string.hpp (original)
+++ trunk/boost/interprocess/containers/string.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -50,6 +50,8 @@
#include <memory>
#include <algorithm>
#include <iosfwd>
+#include <istream>
+#include <ostream>
#include <ios>
#include <locale>
#include <cstddef>
Modified: trunk/boost/interprocess/containers/vector.hpp
==============================================================================
--- trunk/boost/interprocess/containers/vector.hpp (original)
+++ trunk/boost/interprocess/containers/vector.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -68,6 +68,7 @@
#include <boost/interprocess/detail/move_iterator.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/detail/mpl.hpp>
+#include <boost/interprocess/detail/advanced_insert_int.hpp>
namespace boost {
namespace interprocess {
@@ -233,22 +234,72 @@
{ return static_cast<const vector_const_iterator<Pointer>&>(*this) - right; }
};
-//!This struct deallocates and allocated memory
-template <class A>
-struct vector_alloc_holder
+template <class T, class A>
+struct vector_value_traits
{
- typedef typename A::pointer pointer;
- typedef typename A::size_type size_type;
- typedef typename A::value_type value_type;
-
+ typedef T value_type;
+ typedef A allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
static const bool trivial_dctr_after_move =
- has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
+ has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
static const bool trivial_copy = has_trivial_copy<value_type>::value;
static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
static const bool trivial_assign = has_trivial_assign<value_type>::value;
static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
+ //This is the anti-exception array destructor
+ //to deallocate values already constructed
+ typedef typename detail::if_c
+ <trivial_dctr
+ ,detail::null_scoped_destructor_n<allocator_type>
+ ,detail::scoped_destructor_n<allocator_type>
+ >::type OldArrayDestructor;
+ //This is the anti-exception array destructor
+ //to destroy objects created with copy construction
+ typedef typename detail::if_c
+ <nothrow_copy
+ ,detail::null_scoped_destructor_n<allocator_type>
+ ,detail::scoped_destructor_n<allocator_type>
+ >::type UCopiedArrayDestructor;
+ //This is the anti-exception array deallocator
+ typedef typename detail::if_c
+ <nothrow_copy
+ ,detail::null_scoped_array_deallocator<allocator_type>
+ ,detail::scoped_array_deallocator<allocator_type>
+ >::type UCopiedArrayDeallocator;
+
+ //This is the optimized move iterator for copy constructors
+ //so that std::copy and similar can use memcpy
+ typedef typename detail::if_c
+ <trivial_copy
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ || !is_movable<value_type>::value
+ #endif
+ ,const T*
+ ,detail::move_iterator<T*>
+ >::type copy_move_it;
+
+ //This is the optimized move iterator for assignments
+ //so that std::uninitialized_copy and similar can use memcpy
+ typedef typename detail::if_c
+ <trivial_assign
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ || !is_movable<value_type>::value
+ #endif
+ ,const T*
+ ,detail::move_iterator<T*>
+ >::type assign_move_it;
+};
+
+//!This struct deallocates and allocated memory
+template <class A>
+struct vector_alloc_holder
+{
+ typedef typename A::pointer pointer;
+ typedef typename A::size_type size_type;
+ typedef typename A::value_type value_type;
+ typedef vector_value_traits<value_type, A> value_traits;
+
//Constructor, does not throw
vector_alloc_holder(const A &a)
: members_(a)
@@ -336,13 +387,13 @@
void destroy(value_type* p)
{
- if(!trivial_dctr)
+ if(!value_traits::trivial_dctr)
detail::get_pointer(p)->~value_type();
}
void destroy_n(value_type* p, size_type n)
{
- if(!trivial_dctr)
+ if(!value_traits::trivial_dctr)
for(; n--; ++p) p->~value_type();
}
@@ -398,10 +449,12 @@
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
//! The stored allocator type
- typedef allocator_type stored_allocator_type;
+ typedef allocator_type stored_allocator_type;
/// @cond
private:
+ typedef detail::advanced_insert_aux_int<T, T*> advanced_insert_aux_int_t;
+ typedef detail::vector_value_traits<value_type, A> value_traits;
typedef typename base_t::allocator_v1 allocator_v1;
typedef typename base_t::allocator_v2 allocator_v2;
@@ -410,48 +463,6 @@
typedef constant_iterator<T, difference_type> cvalue_iterator;
typedef repeat_iterator<T, difference_type> repeat_it;
typedef detail::move_iterator<repeat_it> repeat_move_it;
- //This is the anti-exception array destructor
- //to deallocate values already constructed
- typedef typename detail::if_c
- <base_t::trivial_dctr
- ,detail::null_scoped_destructor_n<allocator_type>
- ,detail::scoped_destructor_n<allocator_type>
- >::type OldArrayDestructor;
- //This is the anti-exception array destructor
- //to destroy objects created with copy construction
- typedef typename detail::if_c
- <base_t::nothrow_copy
- ,detail::null_scoped_destructor_n<allocator_type>
- ,detail::scoped_destructor_n<allocator_type>
- >::type UCopiedArrayDestructor;
- //This is the anti-exception array deallocator
- typedef typename detail::if_c
- <base_t::nothrow_copy
- ,detail::null_scoped_array_deallocator<allocator_type>
- ,detail::scoped_array_deallocator<allocator_type>
- >::type UCopiedArrayDeallocator;
-
- //This is the optimized move iterator for copy constructors
- //so that std::copy and similar can use memcpy
- typedef typename detail::if_c
- <base_t::trivial_copy
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- || !is_movable<value_type>::value
- #endif
- ,T*
- ,detail::move_iterator<T*>
- >::type copy_move_it;
-
- //This is the optimized move iterator for assignments
- //so that std::uninitialized_copy and similar can use memcpy
- typedef typename detail::if_c
- <base_t::trivial_assign
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- || !is_movable<value_type>::value
- #endif
- ,T*
- ,detail::move_iterator<T*>
- >::type assign_move_it;
/// @endcond
public:
@@ -475,7 +486,7 @@
vector(size_type n, const T& value = T(),
const allocator_type& a = allocator_type())
: base_t(a)
- { this->insert(this->end(), n, value); }
+ { this->insert(this->cend(), n, value); }
//! <b>Effects</b>: Copy constructs a vector.
//!
@@ -552,7 +563,7 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator end() const
- { return const_iterator(this->members_.m_start + this->members_.m_size); }
+ { return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed vector.
@@ -570,7 +581,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rbegin()const
- { return const_reverse_iterator(this->end());}
+ { return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed vector.
@@ -588,6 +599,40 @@
//!
//! <b>Complexity</b>: Constant.
const_reverse_iterator rend() const
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const
+ { return const_iterator(this->members_.m_start); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const
+ { return const_iterator(this->members_.m_start + this->members_.m_size); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin()const
+ { return const_reverse_iterator(this->end());}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const
{ return const_reverse_iterator(this->begin()); }
//! <b>Requires</b>: !empty()
@@ -623,8 +668,6 @@
reference back()
{ return this->members_.m_start[this->members_.m_size - 1]; }
- //! <b>Requires</b>: !empty()
- //!
//! <b>Effects</b>: Returns a const reference to the first element
//! from the beginning of the container.
//!
@@ -634,6 +677,24 @@
const_reference back() const
{ return this->members_.m_start[this->members_.m_size - 1]; }
+ //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ pointer data()
+ { return this->members_.m_start; }
+
+ //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_pointer data() const
+ { return this->members_.m_start; }
+
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
//!
//! <b>Throws</b>: Nothing.
@@ -754,7 +815,9 @@
//If there is no forward expansion, move objects
else{
//We will reuse insert code, so create a dummy input iterator
- copy_move_it dummy_it(detail::get_pointer(this->members_.m_start));
+ typename value_traits::copy_move_it dummy_it(detail::get_pointer(this->members_.m_start));
+ detail::advanced_insert_aux_proxy<T, typename value_traits::copy_move_it, T*>
+ proxy(dummy_it, dummy_it);
//Backwards (and possibly forward) expansion
if(ret.second){
#ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
@@ -764,9 +827,8 @@
( detail::get_pointer(ret.first)
, real_cap
, detail::get_pointer(this->members_.m_start)
- , dummy_it
- , dummy_it
- , 0);
+ , 0
+ , proxy);
}
//New buffer
else{
@@ -777,8 +839,8 @@
( detail::get_pointer(ret.first)
, real_cap
, detail::get_pointer(this->members_.m_start)
- , dummy_it
- , dummy_it);
+ , 0
+ , proxy);
}
}
}
@@ -812,25 +874,16 @@
vector<T, A>& operator=(const detail::moved_object<vector<T, A> >& mx)
{
vector<T, A> &x = mx.get();
-
- if (&x != this){
- this->swap(x);
- x.clear();
- }
- return *this;
- }
#else
- vector<T, A>& operator=(vector<T, A> && mx)
+ vector<T, A>& operator=(vector<T, A> && x)
{
- vector<T, A> &x = mx;
-
+ #endif
if (&x != this){
this->swap(x);
x.clear();
}
return *this;
}
- #endif
//! <b>Effects</b>: Assigns the n copies of val to *this.
//!
@@ -869,7 +922,7 @@
++this->members_.m_size;
}
else{
- this->insert(this->end(), x);
+ this->insert(this->cend(), x);
}
}
@@ -882,28 +935,122 @@
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void push_back(const detail::moved_object<T> & mx)
{
+ value_type &x = mx.get();
+ #else
+ void push_back(T && x)
+ {
+ #endif
+ if (this->members_.m_size < this->members_.m_capacity){
+ //There is more memory, just construct a new object at the end
+ new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(detail::move_impl(x));
+ ++this->members_.m_size;
+ }
+ else{
+ this->insert(this->cend(), detail::move_impl(x));
+ }
+ }
+
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template<class ...Args>
+ void emplace_back(Args &&...args)
+ {
+ T* back_pos = detail::get_pointer(this->members_.m_start) + this->members_.m_size;
if (this->members_.m_size < this->members_.m_capacity){
//There is more memory, just construct a new object at the end
- new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(mx);
+ new((void*)(back_pos))value_type(detail::forward_impl<Args>(args)...);
++this->members_.m_size;
}
else{
- this->insert(this->end(), mx);
+ detail::advanced_insert_aux_emplace<T, T*, Args...> proxy
+ (detail::forward_impl<Args>(args)...);
+ priv_range_insert(back_pos, 1, proxy);
}
}
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before position
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ template<class ...Args>
+ iterator emplace(const_iterator position, Args && ...args)
+ {
+ //Just call more general insert(pos, size, value) and return iterator
+ size_type pos_n = position - cbegin();
+ detail::advanced_insert_aux_emplace<T, T*, Args...> proxy
+ (detail::forward_impl<Args>(args)...);
+ priv_range_insert(position.get_ptr(), 1, proxy);
+ return iterator(this->members_.m_start + pos_n);
+ }
+
#else
- void push_back(T && mx)
+
+ void emplace_back()
{
+ T* back_pos = detail::get_pointer(this->members_.m_start) + this->members_.m_size;
if (this->members_.m_size < this->members_.m_capacity){
//There is more memory, just construct a new object at the end
- new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(detail::move_impl(mx));
+ new((void*)(back_pos))value_type();
++this->members_.m_size;
}
else{
- this->insert(this->end(), detail::move_impl(mx));
+ detail::advanced_insert_aux_emplace<value_type, T*> proxy;
+ priv_range_insert(back_pos, 1, proxy);
}
}
- #endif
+
+ iterator emplace(const_iterator position)
+ {
+ size_type pos_n = position - cbegin();
+ detail::advanced_insert_aux_emplace<value_type, T*> proxy;
+ priv_range_insert(detail::get_pointer(position.get_ptr()), 1, proxy);
+ return iterator(this->members_.m_start + pos_n);
+ }
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ T* back_pos = detail::get_pointer(this->members_.m_start) + this->members_.m_size; \
+ if (this->members_.m_size < this->members_.m_capacity){ \
+ new((void*)(back_pos))value_type \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ ++this->members_.m_size; \
+ } \
+ else{ \
+ detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)> \
+ proxy(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_range_insert(back_pos, 1, proxy); \
+ } \
+ } \
+ \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ { \
+ size_type pos_n = pos - cbegin(); \
+ detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)> \
+ proxy(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ priv_range_insert(detail::get_pointer(pos.get_ptr()), 1, proxy); \
+ return iterator(this->members_.m_start + pos_n); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
//! <b>Effects</b>: Swaps the contents of *this and x.
//! If this->allocator_type() != x.allocator_type()
@@ -912,7 +1059,11 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(vector<T, A>& x)
+ #else
+ void swap(vector<T, A> && x)
+ #endif
{
allocator_type &this_al = this->alloc(), &other_al = x.alloc();
//Just swap internals
@@ -925,6 +1076,7 @@
}
}
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
//! <b>Effects</b>: Swaps the contents of *this and x.
//! If this->allocator_type() != x.allocator_type()
//! allocators are also swapped.
@@ -932,18 +1084,11 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
void swap(const detail::moved_object<vector<T, A> >& mx)
{
vector<T, A> &x = mx.get();
this->swap(x);
}
- #else
- void swap(vector<T, A> && mx)
- {
- vector<T, A> &x = mx;
- this->swap(x);
- }
#endif
//! <b>Requires</b>: position must be a valid iterator of *this.
@@ -952,14 +1097,14 @@
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
- //! <b>Complexity</b>: If position is begin() or end(), amortized constant time
+ //! <b>Complexity</b>: If position is end(), amortized constant time
//! Linear time otherwise.
- iterator insert(iterator position, const T& x)
+ iterator insert(const_iterator position, const T& x)
{
//Just call more general insert(pos, size, value) and return iterator
- size_type n = position - begin();
+ size_type pos_n = position - cbegin();
this->insert(position, (size_type)1, x);
- return iterator(this->members_.m_start + n);
+ return iterator(this->members_.m_start + pos_n);
}
//! <b>Requires</b>: position must be a valid iterator of *this.
@@ -968,29 +1113,23 @@
//!
//! <b>Throws</b>: If memory allocation throws.
//!
- //! <b>Complexity</b>: If position is begin() or end(), amortized constant time
+ //! <b>Complexity</b>: If position is end(), amortized constant time
//! Linear time otherwise.
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- iterator insert(iterator position, const detail::moved_object<T> &mx)
+ iterator insert(const_iterator position, const detail::moved_object<T> &mx)
{
- //Just call more general insert(pos, size, value) and return iterator
- size_type n = position - begin();
- this->insert(position
- ,repeat_move_it(repeat_it(mx.get(), 1))
- ,repeat_move_it(repeat_it()));
- return iterator(this->members_.m_start + n);
- }
+ value_type &x = mx.get();
#else
- iterator insert(iterator position, T &&mx)
+ iterator insert(const_iterator position, T &&x)
{
+ #endif
//Just call more general insert(pos, size, value) and return iterator
- size_type n = position - begin();
+ size_type pos_n = position - cbegin();
this->insert(position
- ,repeat_move_it(repeat_it(mx, 1))
+ ,repeat_move_it(repeat_it(x, 1))
,repeat_move_it(repeat_it()));
- return iterator(this->members_.m_start + n);
+ return iterator(this->members_.m_start + pos_n);
}
- #endif
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
@@ -1001,7 +1140,7 @@
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InIt>
- void insert(iterator pos, InIt first, InIt last)
+ void insert(const_iterator pos, InIt first, InIt last)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = detail::is_convertible<InIt, std::size_t>::value;
@@ -1016,7 +1155,7 @@
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- void insert (iterator p, size_type n, const T& x)
+ void insert(const_iterator p, size_type n, const T& x)
{ this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); }
//! <b>Effects</b>: Removes the last element from the vector.
@@ -1041,7 +1180,7 @@
{
T *pos = detail::get_pointer(position.get_ptr());
T *beg = detail::get_pointer(this->members_.m_start);
-
+ typedef typename value_traits::assign_move_it assign_move_it;
std::copy(assign_move_it(pos + 1), assign_move_it(beg + this->members_.m_size), pos);
--this->members_.m_size;
//Destroy last element
@@ -1056,6 +1195,7 @@
//! <b>Complexity</b>: Linear to the distance between first and last.
iterator erase(const_iterator first, const_iterator last)
{
+ typedef typename value_traits::assign_move_it assign_move_it;
if (first != last){ // worth doing, copy down over hole
T* end_pos = detail::get_pointer(this->members_.m_start) + this->members_.m_size;
T* ptr = detail::get_pointer(std::copy
@@ -1081,11 +1221,11 @@
pointer finish = this->members_.m_start + this->members_.m_size;
if (new_size < size()){
//Destroy last elements
- this->erase(iterator(this->members_.m_start + new_size), this->end());
+ this->erase(const_iterator(this->members_.m_start + new_size), this->end());
}
else{
//Insert new elements at the end
- this->insert(iterator(finish), new_size - this->size(), x);
+ this->insert(const_iterator(finish), new_size - this->size(), x);
}
}
@@ -1099,17 +1239,13 @@
{
if (new_size < this->size()){
//Destroy last elements
- this->erase(iterator(this->members_.m_start + new_size), this->end());
+ this->erase(const_iterator(this->members_.m_start + new_size), this->end());
}
else{
size_type n = new_size - this->size();
this->reserve(new_size);
- T *ptr = detail::get_pointer(this->members_.m_start + this->members_.m_size);
- while(n--){
- //Default construct
- new((void*)ptr++)T();
- ++this->members_.m_size;
- }
+ detail::default_construct_aux_proxy<T, T*, size_type> proxy(n);
+ priv_range_insert(this->cend().get_ptr(), n, proxy);
}
}
@@ -1174,76 +1310,86 @@
}
template <class FwdIt>
- void priv_range_insert(pointer pos, FwdIt first,
- FwdIt last, std::forward_iterator_tag)
+ void priv_range_insert(pointer pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
{
- if (first != last){
- size_type n = std::distance(first, last);
- //Check if we have enough memory or try to expand current memory
- size_type remaining = this->members_.m_capacity - this->members_.m_size;
- bool same_buffer_start;
- std::pair<pointer, bool> ret;
- size_type real_cap = this->members_.m_capacity;
+ if(first != last){
+ const size_type n = std::distance(first, last);
+ detail::advanced_insert_aux_proxy<T, FwdIt, T*> proxy(first, last);
+ priv_range_insert(pos, n, proxy);
+ }
+ }
- //Check if we already have room
- if (n <= remaining){
- same_buffer_start = true;
- }
- else{
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- size_type new_cap = this->next_capacity(n);
- ret = this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- this->members_.m_size + n, new_cap, real_cap, this->members_.m_start);
-
- //Check for forward expansion
- same_buffer_start = ret.second && this->members_.m_start == ret.first;
- if(same_buffer_start){
- this->members_.m_capacity = real_cap;
- }
- }
-
- //If we had room or we have expanded forward
- if (same_buffer_start){
- #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->priv_range_insert_expand_forward
- (detail::get_pointer(pos), first, last, n);
- }
- //Backwards (and possibly forward) expansion
- else if(ret.second){
- #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( detail::get_pointer(ret.first)
- , real_cap
- , detail::get_pointer(pos)
- , first
- , last
- , n);
- }
- //New buffer
- else{
- #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( detail::get_pointer(ret.first)
- , real_cap
- , detail::get_pointer(pos)
- , first
- , last);
+ void priv_range_insert(pointer pos, const size_type n,
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+ advanced_insert_aux_int_t &&interf
+ #else
+ advanced_insert_aux_int_t &interf
+ #endif
+ )
+ {
+ //Check if we have enough memory or try to expand current memory
+ size_type remaining = this->members_.m_capacity - this->members_.m_size;
+ bool same_buffer_start;
+ std::pair<pointer, bool> ret;
+ size_type real_cap = this->members_.m_capacity;
+
+ //Check if we already have room
+ if (n <= remaining){
+ same_buffer_start = true;
+ }
+ else{
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ size_type new_cap = this->next_capacity(n);
+ ret = this->allocation_command
+ (allocate_new | expand_fwd | expand_bwd,
+ this->members_.m_size + n, new_cap, real_cap, this->members_.m_start);
+
+ //Check for forward expansion
+ same_buffer_start = ret.second && this->members_.m_start == ret.first;
+ if(same_buffer_start){
+ this->members_.m_capacity = real_cap;
}
}
+
+ //If we had room or we have expanded forward
+ if (same_buffer_start){
+ #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->priv_range_insert_expand_forward
+ (detail::get_pointer(pos), n, interf);
+ }
+ //Backwards (and possibly forward) expansion
+ else if(ret.second){
+ #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
+ ++this->num_expand_bwd;
+ #endif
+ this->priv_range_insert_expand_backwards
+ ( detail::get_pointer(ret.first)
+ , real_cap
+ , detail::get_pointer(pos)
+ , n
+ , interf);
+ }
+ //New buffer
+ else{
+ #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_range_insert_new_allocation
+ ( detail::get_pointer(ret.first)
+ , real_cap
+ , detail::get_pointer(pos)
+ , n
+ , interf);
+ }
}
- template <class FwdIt>
- void priv_range_insert_expand_forward
- (T* pos, FwdIt first, FwdIt last, size_type n)
+ void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf)
{
+ typedef typename value_traits::copy_move_it copy_move_it;
+ typedef typename value_traits::assign_move_it assign_move_it;
//There is enough memory
T* old_finish = detail::get_pointer(this->members_.m_start) + this->members_.m_size;
const size_type elems_after = old_finish - pos;
@@ -1256,35 +1402,32 @@
//Copy previous to last objects to the initialized end
std::copy_backward(assign_move_it(pos), assign_move_it(old_finish - n), old_finish);
//Insert new objects in the pos
- std::copy(first, last, pos);
+ interf.copy_all_to(pos);
}
else {
//The new elements don't fit in the [pos, end()) range. Copy
//to the beginning of the unallocated zone the last new elements.
- FwdIt mid = first;
- std::advance(mid, elems_after);
- std::uninitialized_copy(mid, last, old_finish);
+ interf.uninitialized_copy_some_and_update(old_finish, elems_after, false);
this->members_.m_size += n - elems_after;
//Copy old [pos, end()) elements to the uninitialized memory
std::uninitialized_copy
- ( copy_move_it(pos)
- , copy_move_it(old_finish)
+ ( copy_move_it(pos), copy_move_it(old_finish)
, detail::get_pointer(this->members_.m_start) + this->members_.m_size);
this->members_.m_size += elems_after;
//Copy first new elements in pos
- std::copy(first, mid, pos);
+ interf.copy_all_to(pos);
}
}
- template <class FwdIt>
void priv_range_insert_new_allocation
- (T* new_start, size_type new_cap, T* pos, FwdIt first, FwdIt last)
+ (T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf)
{
+ typedef typename value_traits::copy_move_it copy_move_it;
T* new_finish = new_start;
T *old_finish;
//Anti-exception rollbacks
- UCopiedArrayDeallocator scoped_alloc(new_start, this->alloc(), new_cap);
- UCopiedArrayDestructor construted_values_destroyer(new_start, 0u);
+ typename value_traits::UCopiedArrayDeallocator scoped_alloc(new_start, this->alloc(), new_cap);
+ typename value_traits::UCopiedArrayDestructor constructed_values_destroyer(new_start, 0u);
//Initialize with [begin(), pos) old buffer
//the start of the new buffer
@@ -1292,11 +1435,11 @@
( copy_move_it(detail::get_pointer(this->members_.m_start))
, copy_move_it(pos)
, old_finish = new_finish);
- construted_values_destroyer.increment_size(new_finish - old_finish);
+ constructed_values_destroyer.increment_size(new_finish - old_finish);
//Initialize new objects, starting from previous point
- new_finish = std::uninitialized_copy
- (first, last, old_finish = new_finish);
- construted_values_destroyer.increment_size(new_finish - old_finish);
+ interf.uninitialized_copy_all_to(old_finish = new_finish);
+ new_finish += n;
+ constructed_values_destroyer.increment_size(new_finish - old_finish);
//Initialize from the rest of the old buffer,
//starting from previous point
new_finish = std::uninitialized_copy
@@ -1305,12 +1448,12 @@
, new_finish);
//All construction successful, disable rollbacks
- construted_values_destroyer.release();
+ constructed_values_destroyer.release();
scoped_alloc.release();
//Destroy and deallocate old elements
//If there is allocated memory, destroy and deallocate
if(this->members_.m_start != 0){
- if(!base_t::trivial_dctr_after_move)
+ if(!value_traits::trivial_dctr_after_move)
this->destroy_n(detail::get_pointer(this->members_.m_start), this->members_.m_size);
this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
}
@@ -1319,11 +1462,13 @@
this->members_.m_capacity = new_cap;
}
- template <class FwdIt>
void priv_range_insert_expand_backwards
(T* new_start, size_type new_capacity,
- T* pos, FwdIt first, FwdIt last, size_type n)
+ T* pos, const size_type n, advanced_insert_aux_int_t &interf)
{
+ typedef typename value_traits::copy_move_it copy_move_it;
+ typedef typename value_traits::assign_move_it assign_move_it;
+
//Backup old data
T* old_start = detail::get_pointer(this->members_.m_start);
T* old_finish = old_start + this->members_.m_size;
@@ -1340,74 +1485,70 @@
//If anything goes wrong, this object will destroy
//all the old objects to fulfill previous vector state
- OldArrayDestructor old_values_destroyer(old_start, old_size);
-
- //Check if s_before is so big that even copying the old data + new data
- //there is a gap between the new data and the old data
- if(s_before >= (old_size + n)){
- //Old situation:
- // _________________________________________________________
- //| raw_mem | old_begin | old_end |
- //| __________________________________|___________|_________|
- //
- //New situation:
- // _________________________________________________________
- //| old_begin | new | old_end | raw_mem |
- //|___________|__________|_________|________________________|
- //
- //Copy first old values before pos, after that the
- //new objects
- boost::interprocess::uninitialized_copy_copy
- (copy_move_it(old_start), copy_move_it(pos), first, last, new_start);
- UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore);
- //Now initialize the rest of memory with the last old values
- std::uninitialized_copy
- (copy_move_it(pos), copy_move_it(old_finish), new_start + elemsbefore + n);
- //All new elements correctly constructed, avoid new element destruction
- new_values_destroyer.release();
- this->members_.m_size = old_size + n;
- //Old values destroyed automatically with "old_values_destroyer"
- //when "old_values_destroyer" goes out of scope unless the have trivial
- //destructor after move.
- if(base_t::trivial_dctr_after_move)
+ typename value_traits::OldArrayDestructor old_values_destroyer(old_start, old_size);
+ //Check if s_before is big enough to hold the beginning of old data + new data
+ if(difference_type(s_before) >= difference_type(elemsbefore + n)){
+ //Copy first old values before pos, after that the new objects
+ std::uninitialized_copy(copy_move_it(old_start), copy_move_it(pos), new_start);
+ this->members_.m_size = elemsbefore;
+ interf.uninitialized_copy_all_to(new_start + elemsbefore);
+ this->members_.m_size += n;
+ //Check if s_before is so big that even copying the old data + new data
+ //there is a gap between the new data and the old data
+ if(s_before >= (old_size + n)){
+ //Old situation:
+ // _________________________________________________________
+ //| raw_mem | old_begin | old_end |
+ //| __________________________________|___________|_________|
+ //
+ //New situation:
+ // _________________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|__________|_________|________________________|
+ //
+ //Now initialize the rest of memory with the last old values
+ std::uninitialized_copy
+ (copy_move_it(pos), copy_move_it(old_finish), new_start + elemsbefore + n);
+ //All new elements correctly constructed, avoid new element destruction
+ this->members_.m_size = old_size + n;
+ //Old values destroyed automatically with "old_values_destroyer"
+ //when "old_values_destroyer" goes out of scope unless the have trivial
+ //destructor after move.
+ if(value_traits::trivial_dctr_after_move)
+ old_values_destroyer.release();
+ }
+ //s_before is so big that divides old_end
+ else{
+ //Old situation:
+ // __________________________________________________
+ //| raw_mem | old_begin | old_end |
+ //| ___________________________|___________|_________|
+ //
+ //New situation:
+ // __________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|__________|_________|_________________|
+ //
+ //Now initialize the rest of memory with the last old values
+ //All new elements correctly constructed, avoid new element destruction
+ size_type raw_gap = s_before - (elemsbefore + n);
+ //Now initialize the rest of s_before memory with the
+ //first of elements after new values
+ std::uninitialized_copy
+ (copy_move_it(pos), copy_move_it(pos + raw_gap), new_start + elemsbefore + n);
+ //Update size since we have a contiguous buffer
+ this->members_.m_size = old_size + s_before;
+ //All new elements correctly constructed, avoid old element destruction
old_values_destroyer.release();
- }
- //Check if s_before is so big that divides old_end
- else if(difference_type(s_before) >= difference_type(elemsbefore + n)){
- //Old situation:
- // __________________________________________________
- //| raw_mem | old_begin | old_end |
- //| ___________________________|___________|_________|
- //
- //New situation:
- // __________________________________________________
- //| old_begin | new | old_end | raw_mem |
- //|___________|__________|_________|_________________|
- //
- //Copy first old values before pos, after that the
- //new objects
- boost::interprocess::uninitialized_copy_copy
- (copy_move_it(old_start), copy_move_it(pos), first, last, new_start);
- UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore);
- size_type raw_gap = s_before - (elemsbefore + n);
- //Now initialize the rest of s_before memory with the
- //first of elements after new values
- std::uninitialized_copy
- (copy_move_it(pos), copy_move_it(pos + raw_gap), new_start + elemsbefore + n);
- //All new elements correctly constructed, avoid new element destruction
- new_values_destroyer.release();
- //All new elements correctly constructed, avoid old element destruction
- old_values_destroyer.release();
- //Update size since we have a contiguous buffer
- this->members_.m_size = old_size + s_before;
- //Now copy remaining last objects in the old buffer begin
- T *to_destroy = std::copy(assign_move_it(pos + raw_gap), assign_move_it(old_finish), old_start);
- //Now destroy redundant elements except if they were moved and
- //they have trivial destructor after move
- size_type n_destroy = old_finish - to_destroy;
- if(!base_t::trivial_dctr_after_move)
- this->destroy_n(to_destroy, n_destroy);
- this->members_.m_size -= n_destroy;
+ //Now copy remaining last objects in the old buffer begin
+ T *to_destroy = std::copy(assign_move_it(pos + raw_gap), assign_move_it(old_finish), old_start);
+ //Now destroy redundant elements except if they were moved and
+ //they have trivial destructor after move
+ size_type n_destroy = old_finish - to_destroy;
+ if(!value_traits::trivial_dctr_after_move)
+ this->destroy_n(to_destroy, n_destroy);
+ this->members_.m_size -= n_destroy;
+ }
}
else{
//Check if we have to do the insertion in two phases
@@ -1430,13 +1571,6 @@
//|____________________________|____________________|
//
bool do_after = n > s_before;
- FwdIt before_end = first;
- //If we have to expand both sides,
- //we will play if the first new values so
- //calculate the upper bound of new values
- if(do_after){
- std::advance(before_end, s_before);
- }
//Now we can have two situations: the raw_mem of the
//beginning divides the old_begin, or the new elements:
@@ -1466,8 +1600,7 @@
//
//Copy the first part of old_begin to raw_mem
T *start_n = old_start + difference_type(s_before);
- std::uninitialized_copy
- (copy_move_it(old_start), copy_move_it(start_n), new_start);
+ std::uninitialized_copy(copy_move_it(old_start), copy_move_it(start_n), new_start);
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
@@ -1476,22 +1609,27 @@
T* next = std::copy(assign_move_it(start_n), assign_move_it(pos), old_start);
if(do_after){
//Now copy the new_beg elements
- std::copy(first, before_end, next);
+ interf.copy_some_and_update(next, s_before, true);
}
else{
//Now copy the all the new elements
- T* move_start = std::copy(first, last, next);
+ interf.copy_all_to(next);
+ T* move_start = next + n;
//Now displace old_end elements
T* move_end = std::copy(assign_move_it(pos), assign_move_it(old_finish), move_start);
//Destroy remaining moved elements from old_end except if
//they have trivial destructor after being moved
difference_type n_destroy = s_before - n;
- if(!base_t::trivial_dctr_after_move)
+ if(!value_traits::trivial_dctr_after_move)
this->destroy_n(move_end, n_destroy);
this->members_.m_size -= n_destroy;
}
}
else {
+ //If we have to expand both sides,
+ //we will play if the first new values so
+ //calculate the upper bound of new values
+
//The raw memory divides the new elements
//
//If we need two phase construction (do_after)
@@ -1514,29 +1652,30 @@
//|___________|_____|_________|__________________________|
//
//First copy whole old_begin and part of new to raw_mem
- FwdIt mid = first;
- size_type n_new_init = difference_type(s_before) - elemsbefore;
- std::advance(mid, n_new_init);
- boost::interprocess::uninitialized_copy_copy
- (copy_move_it(old_start), copy_move_it(pos), first, mid, new_start);
+ std::uninitialized_copy(copy_move_it(old_start), copy_move_it(pos), new_start);
+ this->members_.m_size = elemsbefore;
+
+ const size_type mid_n = difference_type(s_before) - elemsbefore;
+ interf.uninitialized_copy_some_and_update(new_start + elemsbefore, mid_n, true);
+ this->members_.m_size = old_size + s_before;
//The buffer is all constructed until old_end,
//release destroyer and update size
old_values_destroyer.release();
- this->members_.m_size = old_size + s_before;
if(do_after){
//Copy new_beg part
- std::copy(mid, before_end, old_start);
+ interf.copy_some_and_update(old_start, s_before - mid_n, true);
}
else{
//Copy all new elements
- T* move_start = std::copy(mid, last, old_start);
+ interf.copy_all_to(old_start);
+ T* move_start = old_start + (n-mid_n);
//Displace old_end
T* move_end = std::copy(copy_move_it(pos), copy_move_it(old_finish), move_start);
//Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved
difference_type n_destroy = s_before - n;
- if(!base_t::trivial_dctr_after_move)
+ if(!value_traits::trivial_dctr_after_move)
this->destroy_n(move_end, n_destroy);
this->members_.m_size -= n_destroy;
}
@@ -1567,9 +1706,6 @@
const size_type n_after = n - s_before;
const difference_type elemsafter = old_size - elemsbefore;
- //The new_end part is [first + (n - n_after), last)
- std::advance(first, n - n_after);
-
//We can have two situations:
if (elemsafter > difference_type(n_after)){
//The raw_mem from end will divide displaced old_end
@@ -1592,7 +1728,8 @@
//Displace the rest of old_end to the new position
std::copy_backward(assign_move_it(pos), assign_move_it(finish_n), old_finish);
//Now overwrite with new_end
- std::copy(first, last, pos);
+ //The new_end part is [first + (n - n_after), last)
+ interf.copy_all_to(pos);
}
else {
//The raw_mem from end will divide new_end part
@@ -1607,45 +1744,44 @@
//| old_begin + new_beg | new_end |old_end | raw_mem |
//|__________________________|_______________|________|_________|
//
- FwdIt mid = first;
- std::advance(mid, elemsafter);
+ size_type mid_last_dist = n_after - elemsafter;
//First initialize data in raw memory
- boost::interprocess::uninitialized_copy_copy
- ( mid, last, copy_move_it(pos), copy_move_it(old_finish), old_finish);
- this->members_.m_size += n_after;
+ //The new_end part is [first + (n - n_after), last)
+ interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
+ this->members_.m_size += mid_last_dist;
+ std::uninitialized_copy(copy_move_it(pos), copy_move_it(old_finish), old_finish + mid_last_dist);
+ this->members_.m_size += n_after - mid_last_dist;
//Now copy the part of new_end over constructed elements
- std::copy(first, mid, pos);
+ interf.copy_all_to(pos);
}
}
}
}
template <class InIt>
- void priv_range_insert(iterator pos,
- InIt first, InIt last,
- std::input_iterator_tag)
+ void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag)
{
- //Insert range before the pos position
- std::copy(std::inserter(*this, pos), first, last);
+ for(;first != last; ++first){
+ this->insert(pos, detail::move_impl(value_type(*first)));
+ }
}
template <class InIt>
- void priv_assign_aux(InIt first, InIt last,
- std::input_iterator_tag)
+ void priv_assign_aux(InIt first, InIt last, std::input_iterator_tag)
{
//Overwrite all elements we can from [first, last)
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first){
*cur = *first;
}
-
+
if (first == last){
//There are no more elements in the sequence, erase remaining
- this->erase(cur, end());
+ this->erase(cur, cend());
}
else{
//There are more elements in the range, insert the remaining ones
- this->insert(this->end(), first, last);
+ this->insert(this->cend(), first, last);
}
}
@@ -1697,7 +1833,7 @@
}
}
else if(!ret.second){
- UCopiedArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
+ typename value_traits::UCopiedArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
std::uninitialized_copy(first, last, detail::get_pointer(ret.first));
scoped_alloc.release();
//Destroy and deallocate old buffer
@@ -1711,11 +1847,10 @@
}
else{
//Backwards expansion
- //If anything goes wrong, this object will destroy
- //all old objects
+ //If anything goes wrong, this object will destroy old objects
T *old_start = detail::get_pointer(this->members_.m_start);
size_type old_size = this->members_.m_size;
- OldArrayDestructor old_values_destroyer(old_start, old_size);
+ typename value_traits::OldArrayDestructor old_values_destroyer(old_start, old_size);
//If something goes wrong size will be 0
//but holding the whole buffer
this->members_.m_size = 0;
@@ -1725,9 +1860,10 @@
//Backup old buffer data
size_type old_offset = old_start - detail::get_pointer(ret.first);
size_type first_count = min_value(n, old_offset);
- boost::interprocess::uninitialized_copy_n
- (first, first_count, detail::get_pointer(ret.first));
- FwdIt mid = first + first_count;
+
+ FwdIt mid = first;
+ std::advance(mid, first_count);
+ std::uninitialized_copy(first, mid, detail::get_pointer(ret.first));
if(old_offset > n){
//All old elements will be destroyed by "old_values_destroyer"
@@ -1741,16 +1877,14 @@
this->members_.m_size = first_count + old_size;
//Now overwrite the old values
size_type second_count = min_value(old_size, n - first_count);
- copy_n(mid, second_count, old_start);
- mid += second_count;
+ FwdIt mid2 = mid;
+ std::advance(mid2, second_count);
+ std::copy(mid, mid2, old_start);
//Check if we still have to append elements in the
//uninitialized end
if(second_count == old_size){
- boost::interprocess::uninitialized_copy_n
- ( mid
- , n - first_count - second_count
- , old_start + old_size);
+ std::copy(mid2, last, old_start + old_size);
}
else{
//We have to destroy some old values
@@ -1777,11 +1911,11 @@
}
template <class Integer>
- void priv_insert_dispatch( iterator pos, Integer n, Integer val, detail::true_)
+ void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, detail::true_)
{ this->insert(pos, (size_type)n, (T)val); }
template <class InIt>
- void priv_insert_dispatch(iterator pos, InIt first,
+ void priv_insert_dispatch(const_iterator pos, InIt first,
InIt last, detail::false_)
{
//Dispatch depending on integer/iterator
Added: trunk/boost/interprocess/detail/advanced_insert_int.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/advanced_insert_int.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -0,0 +1,395 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
+#define BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/move.hpp>
+#include <iterator> //std::iterator_traits
+#include <algorithm> //std::copy, std::uninitialized_copy
+#include <new> //placement new
+#include <cassert>
+
+namespace boost { namespace interprocess { namespace detail {
+
+//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
+template<class T, class Iterator>
+struct advanced_insert_aux_int
+{
+ typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
+ virtual void copy_all_to(Iterator p) = 0;
+ virtual void uninitialized_copy_all_to(Iterator p) = 0;
+ virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
+ virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
+ virtual ~advanced_insert_aux_int() {}
+};
+
+//This class template will adapt each FwIt types to advanced_insert_aux_int
+template<class T, class FwdIt, class Iterator>
+struct advanced_insert_aux_proxy
+ : public advanced_insert_aux_int<T, Iterator>
+{
+ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
+ advanced_insert_aux_proxy(FwdIt first, FwdIt last)
+ : first_(first), last_(last)
+ {}
+
+ virtual ~advanced_insert_aux_proxy()
+ {}
+
+ virtual void copy_all_to(Iterator p)
+ { *std::copy(first_, last_, p); }
+
+ virtual void uninitialized_copy_all_to(Iterator p)
+ { std::uninitialized_copy(first_, last_, p); }
+
+ virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ {
+ FwdIt mid = first_;
+ std::advance(mid, division_count);
+ if(first_n){
+ std::uninitialized_copy(first_, mid, pos);
+ first_ = mid;
+ }
+ else{
+ std::uninitialized_copy(mid, last_, pos);
+ last_ = mid;
+ }
+ }
+
+ virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ {
+ FwdIt mid = first_;
+ std::advance(mid, division_count);
+ if(first_n){
+ std::copy(first_, mid, pos);
+ first_ = mid;
+ }
+ else{
+ std::copy(mid, last_, pos);
+ last_ = mid;
+ }
+ }
+
+ FwdIt first_, last_;
+};
+
+//This class template will adapt each FwIt types to advanced_insert_aux_int
+template<class T, class Iterator, class SizeType>
+struct default_construct_aux_proxy
+ : public advanced_insert_aux_int<T, Iterator>
+{
+ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
+ default_construct_aux_proxy(SizeType count)
+ : count_(count)
+ {}
+
+ void uninitialized_copy_impl(Iterator p, const SizeType n)
+ {
+ assert(n <= count_);
+ Iterator orig_p = p;
+ SizeType i = 0;
+ try{
+ for(; i < n; ++i, ++p){
+ new(detail::get_pointer(&*p))T();
+ }
+ }
+ catch(...){
+ while(i--){
+ detail::get_pointer(&*orig_p++)->~T();
+ }
+ throw;
+ }
+ count_ -= n;
+ }
+
+ virtual ~default_construct_aux_proxy()
+ {}
+
+ virtual void copy_all_to(Iterator)
+ { //This should never be called with any count
+ assert(count_ == 0);
+ }
+
+ virtual void uninitialized_copy_all_to(Iterator p)
+ { this->uninitialized_copy_impl(p, count_); }
+
+ virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ {
+ SizeType new_count;
+ if(first_n){
+ new_count = division_count;
+ }
+ else{
+ assert(difference_type(count_)>= division_count);
+ new_count = count_ - division_count;
+ }
+ this->uninitialized_copy_impl(pos, new_count);
+ }
+
+ virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
+ {
+ assert(count_ == 0);
+ SizeType new_count;
+ if(first_n){
+ new_count = division_count;
+ }
+ else{
+ assert(difference_type(count_)>= division_count);
+ new_count = count_ - division_count;
+ }
+ //This function should never called with a count different to zero
+ assert(new_count == 0);
+ (void)new_count;
+ }
+
+ SizeType count_;
+};
+
+}}} //namespace boost { namespace interprocess { namespace detail {
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+#include <boost/interprocess/detail/variadic_templates_tools.hpp>
+#include <boost/interprocess/detail/move.hpp>
+#include <typeinfo>
+//#include <iostream> //For debugging purposes
+
+namespace boost {
+namespace interprocess {
+namespace detail {
+
+//This class template will adapt each FwIt types to advanced_insert_aux_int
+template<class T, class Iterator, class ...Args>
+struct advanced_insert_aux_emplace
+ : public advanced_insert_aux_int<T, Iterator>
+{
+ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
+ typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+
+ advanced_insert_aux_emplace(Args&&... args)
+ : args_(args...), used_(false)
+ {}
+
+ ~advanced_insert_aux_emplace()
+ {}
+
+ virtual void copy_all_to(Iterator p)
+ { this->priv_copy_all_to(index_tuple_t(), p); }
+
+ virtual void uninitialized_copy_all_to(Iterator p)
+ { this->priv_uninitialized_copy_all_to(index_tuple_t(), p); }
+
+ virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
+ { this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
+
+ virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
+ { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
+
+ private:
+ template<int ...IdxPack>
+ void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
+ {
+ if(!used_){
+ T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
+ *p = detail::move_impl(object);
+ used_ = true;
+ }
+ }
+
+ template<int ...IdxPack>
+ void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
+ {
+ if(!used_){
+ new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
+ used_ = true;
+ }
+ }
+
+ template<int ...IdxPack>
+ void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
+ {
+ assert(division_count <=1);
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){
+ if(!used_){
+ new(detail::get_pointer(&*p))T(detail::forward_impl<Args>(get<IdxPack>(args_))...);
+ used_ = true;
+ }
+ }
+ }
+
+ template<int ...IdxPack>
+ void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
+ {
+ assert(division_count <=1);
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){
+ if(!used_){
+ T object(detail::forward_impl<Args>(get<IdxPack>(args_))...);
+ *p = detail::move_impl(object);
+ used_ = true;
+ }
+ }
+ }
+ tuple<Args&&...> args_;
+ bool used_;
+};
+
+}}} //namespace boost { namespace interprocess { namespace detail {
+
+#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+#include <boost/interprocess/detail/preprocessor.hpp>
+
+namespace boost {
+namespace interprocess {
+namespace detail {
+
+template<class T>
+struct value_init_helper
+{
+ value_init_helper()
+ : m_t()
+ {}
+
+ T m_t;
+};
+
+//This class template will adapt each FwIt types to advanced_insert_aux_int
+template<class T, class Iterator>
+struct advanced_insert_aux_emplace
+ : public advanced_insert_aux_int<T, Iterator>
+{
+ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
+ advanced_insert_aux_emplace()
+ : used_(false)
+ {}
+
+ ~advanced_insert_aux_emplace()
+ {}
+
+ virtual void copy_all_to(Iterator p)
+ {
+ if(!used_){
+ value_init_helper<T>v;
+ *p = detail::move_impl(v.m_t);
+ used_ = true;
+ }
+ }
+
+ virtual void uninitialized_copy_all_to(Iterator p)
+ {
+ if(!used_){
+ new(detail::get_pointer(&*p))T();
+ used_ = true;
+ }
+ }
+
+ virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
+ {
+ assert(division_count <=1);
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){
+ if(!used_){
+ new(detail::get_pointer(&*p))T();
+ used_ = true;
+ }
+ }
+ }
+
+ virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
+ {
+ assert(division_count <=1);
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){
+ if(!used_){
+ value_init_helper<T>v;
+ *p = detail::move_impl(v.m_t);
+ used_ = true;
+ }
+ }
+ }
+ private:
+ bool used_;
+};
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<class T, class Iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
+ struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ : public advanced_insert_aux_int<T, Iterator> \
+ { \
+ typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; \
+ \
+ BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
+ ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
+ : used_(false), BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
+ \
+ virtual void copy_all_to(Iterator p) \
+ { \
+ if(!used_){ \
+ T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ *p = detail::move_impl(v); \
+ used_ = true; \
+ } \
+ } \
+ \
+ virtual void uninitialized_copy_all_to(Iterator p) \
+ { \
+ if(!used_){ \
+ new(detail::get_pointer(&*p))T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ used_ = true; \
+ } \
+ } \
+ \
+ virtual void uninitialized_copy_some_and_update \
+ (Iterator p, difference_type division_count, bool first_n) \
+ { \
+ assert(division_count <=1); \
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
+ if(!used_){ \
+ new(detail::get_pointer(&*p))T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ used_ = true; \
+ } \
+ } \
+ } \
+ \
+ virtual void copy_some_and_update \
+ (Iterator p, difference_type division_count, bool first_n) \
+ { \
+ assert(division_count <=1); \
+ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
+ if(!used_){ \
+ T v(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ *p = detail::move_impl(v); \
+ used_ = true; \
+ } \
+ } \
+ } \
+ \
+ bool used_; \
+ BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
+ }; \
+//!
+
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+}}} //namespace boost { namespace interprocess { namespace detail {
+
+#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_ADVANCED_INSERT_INT_HPP
Modified: trunk/boost/interprocess/detail/algorithms.hpp
==============================================================================
--- trunk/boost/interprocess/detail/algorithms.hpp (original)
+++ trunk/boost/interprocess/detail/algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -73,7 +73,6 @@
new((void*)dest)T();
}
-
template<class InIt, class OutIt>
struct optimize_assign
{
@@ -108,7 +107,6 @@
: public optimize_copy<const T*, T*>
{};
-
template<class InIt, class OutIt> inline
OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, detail::bool_<false>)
{
@@ -121,7 +119,7 @@
T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
- return ((T*)std::memmove(dest, first, size)) + size;
+ return (static_cast<T*>(std::memmove(dest, first, size))) + size;
}
template<class InIt, class OutIt> inline
@@ -159,13 +157,11 @@
BOOST_CATCH_END
return dest;
}
-
-
template<class T> inline
T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, detail::bool_<true>)
{
std::size_t size = length*sizeof(T);
- return ((T*)std::memmove(dest, first, size)) + size;
+ return (static_cast<T*>(std::memmove(dest, first, size))) + size;
}
template<class InIt, class FwdIt> inline
@@ -178,7 +174,6 @@
return uninitialized_copy_n_dispatch(first, count, dest, detail::bool_<do_optimized_copy>());
}
-
// uninitialized_copy_copy
// Copies [first1, last1) into [result, result + (last1 - first1)), and
// copies [first2, last2) into
@@ -194,7 +189,7 @@
}
BOOST_CATCH(...){
for(;result != mid; ++result){
- result->~value_type();
+ detail::get_pointer(&*result)->~value_type();
}
BOOST_RETHROW
}
Modified: trunk/boost/interprocess/detail/atomic.hpp
==============================================================================
--- trunk/boost/interprocess/detail/atomic.hpp (original)
+++ trunk/boost/interprocess/detail/atomic.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -60,13 +60,13 @@
//! "mem": pointer to the atomic value
//! Returns the old value pointed to by mem
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
-{ return winapi::interlocked_decrement((volatile long*)mem) + 1; }
+{ return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
//! Atomically increment an apr_uint32_t by 1
//! "mem": pointer to the object
//! Returns the old value pointed to by mem
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
-{ return winapi::interlocked_increment((volatile long*)mem)-1; }
+{ return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
//! Atomically read an boost::uint32_t from memory
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
@@ -76,7 +76,7 @@
//! "mem": pointer to the object
//! "param": val value that the object will assume
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
-{ winapi::interlocked_exchange((volatile long*)mem, val); }
+{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
//! Compare an boost::uint32_t's value with "cmp".
//! If they are the same swap the value with "with"
@@ -86,7 +86,7 @@
//! Returns the old value of *mem
inline boost::uint32_t atomic_cas32
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
-{ return winapi::interlocked_compare_exchange((volatile long*)mem, with, cmp); }
+{ return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
} //namespace detail{
} //namespace interprocess{
Modified: trunk/boost/interprocess/detail/config_begin.hpp
==============================================================================
--- trunk/boost/interprocess/detail/config_begin.hpp (original)
+++ trunk/boost/interprocess/detail/config_begin.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -40,4 +40,8 @@
#pragma warning (disable : 4786) // identifier truncated in debug info
#pragma warning (disable : 4996) // "function": was declared deprecated
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
+ #pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
+ // with /GR-; unpredictable behavior may result
+ #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
+ #pragma warning (disable : 4671) // the copy constructor is inaccessible
#endif
Modified: trunk/boost/interprocess/detail/intersegment_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/detail/intersegment_ptr.hpp (original)
+++ trunk/boost/interprocess/detail/intersegment_ptr.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -128,13 +128,13 @@
{
const std::size_t mask = ~(align - 1);
std::size_t beg = this->members.relative.beg;
- return (void*)((((std::size_t)this) & mask) - (beg << align_bits));
+ return reinterpret_cast<void*>((((std::size_t)this) & mask) - (beg << align_bits));
}
void relative_set_begin_from_base(void *addr)
{
- assert(addr < (void*)this);
- std::size_t off = (char*)this - (char*)addr;
+ assert(addr < static_cast<void*>(this));
+ std::size_t off = reinterpret_cast<char*>(this) - reinterpret_cast<char*>(addr);
members.relative.beg = off >> align_bits;
}
@@ -222,7 +222,7 @@
typedef flat_map_intersegment<Mutex> self_t;
void set_from_pointer(const volatile void *ptr)
- { this->set_from_pointer((const void *)ptr); }
+ { this->set_from_pointer(const_cast<const void *>(ptr)); }
//!Obtains the address pointed
//!by the object
@@ -233,7 +233,7 @@
}
switch(this->get_mode()){
case is_relative:
- return (char*)this + members.relative.off;
+ return const_cast<char*>(reinterpret_cast<const char*>(this)) + members.relative.off;
break;
case is_segmented:
{
@@ -241,7 +241,7 @@
std::size_t offset;
void *this_base;
get_segment_info_and_offset(this, segment_info, offset, this_base);
- char *base = (char*)segment_info.group->address_of(this->members.segmented.segment);
+ char *base = static_cast<char*>(segment_info.group->address_of(this->members.segmented.segment));
return base + this->members.segmented.off;
}
break;
@@ -259,7 +259,7 @@
//!This only works with two basic_intersegment_ptr pointing
//!to the same segment. Otherwise undefined
std::ptrdiff_t diff(const self_t &other) const
- { return (char*)this->get_pointer() - (char*)other.get_pointer(); }
+ { return static_cast<char*>(this->get_pointer()) - static_cast<char*>(other.get_pointer()); }
//!Returns true if both point to
//!the same object
@@ -291,14 +291,14 @@
std::size_t mode = this->get_mode();
if(mode == is_in_stack){
- members.direct.addr = (void*)ptr;
+ members.direct.addr = const_cast<void*>(ptr);
return;
}
if(mode == is_relative){
- char *beg_addr = (char*)this->relative_calculate_begin_addr();
+ char *beg_addr = static_cast<char*>(this->relative_calculate_begin_addr());
std::size_t seg_size = this->relative_size();
if(ptr >= beg_addr && ptr < (beg_addr + seg_size)){
- members.relative.off = (char*)ptr - (char*)this;
+ members.relative.off = static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this);
return;
}
}
@@ -312,21 +312,22 @@
if(!this_info.group){
this->set_mode(is_in_stack);
- this->members.direct.addr = (void*)ptr;
+ this->members.direct.addr = const_cast<void*>(ptr);
}
else{
get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base);
if(ptr_info.group != this_info.group){
this->set_mode(is_pointee_outside);
- this->members.direct.addr = (void*)ptr;
+ this->members.direct.addr = const_cast<void*>(ptr);
}
else if(ptr_info.id == this_info.id){
this->set_mode(is_relative);
- members.relative.off = ((char*)ptr - (char*)this);
+ members.relative.off = (static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
this->relative_set_begin_from_base(this_base);
std::size_t pow, frc;
std::size_t s = calculate_size(this_info.size, pow, frc);
+ (void)s;
assert(this_info.size == s);
this->members.relative.pow = pow;
this->members.relative.frc = frc;
@@ -350,14 +351,14 @@
//!offset
void inc_offset(std::ptrdiff_t bytes)
{
- this->set_from_pointer((char*)this->get_pointer()+bytes);
+ this->set_from_pointer(static_cast<char*>(this->get_pointer()) + bytes);
}
//!Decrements internal
//!offset
void dec_offset(std::ptrdiff_t bytes)
{
- this->set_from_pointer((char*)this->get_pointer()-bytes);
+ this->set_from_pointer(static_cast<char*>(this->get_pointer()) - bytes);
}
//////////////////////////////////////
@@ -471,7 +472,7 @@
base = 0;
if(s_map.m_ptr_to_segment_info.empty()){
segment = segment_info_t();
- offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
return;
}
//Find the first base address greater than ptr
@@ -479,22 +480,22 @@
= s_map.m_ptr_to_segment_info.upper_bound(ptr);
if(it == s_map.m_ptr_to_segment_info.begin()){
segment = segment_info_t();
- offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char *>(0);
}
//Go to the previous one
--it;
- char * segment_base = detail::char_ptr_cast(it->first);
+ char * segment_base = const_cast<char*>(reinterpret_cast<const char*>(it->first));
std::size_t segment_size = it->second.size;
- if(segment_base <= detail::char_ptr_cast(ptr) &&
- (segment_base + segment_size) >= detail::char_ptr_cast(ptr)){
+ if(segment_base <= reinterpret_cast<const char*>(ptr) &&
+ (segment_base + segment_size) >= reinterpret_cast<const char*>(ptr)){
segment = it->second;
- offset = detail::char_ptr_cast(ptr) - segment_base;
+ offset = reinterpret_cast<const char*>(ptr) - segment_base;
base = segment_base;
}
else{
segment = segment_info_t();
- offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast();
+ offset = reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0);
}
}
@@ -535,6 +536,7 @@
void *addr = group_id->address_of(group_id->get_size()-1);
group_id->pop_back();
std::size_t erased = s_map.m_ptr_to_segment_info.erase(addr);
+ (void)erased;
assert(erased);
return true;
}
@@ -635,21 +637,6 @@
template<class U>
intersegment_ptr(const intersegment_ptr<U> &r, detail::static_cast_tag)
{ base_t::set_from_pointer(static_cast<T*>(r.get())); }
-/*
- {
- if(r.is_null()){
- base_t::set_from_pointer(0);
- }
- else{
- //Some dirty tricks to safe segment operations.
- //Calculate pointer adjustment and adjust offset.
- pointer ptr = reinterpret_cast<pointer>(this);
- std::ptrdiff_t difference = detail::char_ptr_cast(static_cast<T*>(ptr)) -
- detail::char_ptr_cast(ptr);
- base_t::set_from_other(r);
- base_t::inc_offset(difference*sizeof(T));
- }
- }*/
//!Emulates const_cast operator.
//!Never throws.
@@ -672,7 +659,7 @@
//!Obtains raw pointer from offset.
//!Never throws.
pointer get()const
- { return (pointer)base_t::get_pointer(); }
+ { return static_cast<pointer>(base_t::get_pointer()); }
//!Pointer-like -> operator. It can return 0 pointer.
//!Never throws.
@@ -1001,11 +988,11 @@
return raw_address();
}
else if(this->is_relative()){
- return ((char*)this) + this->relative_pointee_offset();
+ return (const_cast<char*>(reinterpret_cast<const char*>(this))) + this->relative_pointee_offset();
}
else{
group_manager *m = get_segment_group_manager(addr);
- char *base = (char*)m->get_id_address(this->segmented_id());
+ char *base = static_cast<char*>(m->get_id_address(this->segmented_id()));
return base + this->segmented_offset();
}
}
@@ -1039,7 +1026,7 @@
else if(ptr_info.segment_id == this_info.segment_id){
set_relative();
this->relative_size (ptr_info.size);
- this->relative_offset((char*)ptr - (char*)this);
+ this->relative_offset(static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));
this->relative_start (ptr_info.base);
}
}
Modified: trunk/boost/interprocess/detail/managed_memory_impl.hpp
==============================================================================
--- trunk/boost/interprocess/detail/managed_memory_impl.hpp (original)
+++ trunk/boost/interprocess/detail/managed_memory_impl.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -225,7 +225,7 @@
//!Returns the base address of the memory in this process. Never throws.
void * get_address () const
- { return (char*)mp_header - Offset; }
+ { return reinterpret_cast<char*>(mp_header) - Offset; }
//!Returns the size of memory segment. Never throws.
std::size_t get_size () const
@@ -255,21 +255,21 @@
//!The address must belong to the memory segment. Never throws.
handle_t get_handle_from_address (const void *ptr) const
{
- return detail::char_ptr_cast(ptr) -
- detail::char_ptr_cast(this->get_address());
+ return reinterpret_cast<const char*>(ptr) -
+ reinterpret_cast<const char*>(this->get_address());
}
//!Returns true if the address belongs to the managed memory segment
bool belongs_to_segment (const void *ptr) const
{
return ptr >= this->get_address() &&
- ptr < (detail::char_ptr_cast(ptr) + this->get_size());
+ ptr < (reinterpret_cast<const char*>(ptr) + this->get_size());
}
//!Transforms previously obtained offset into an absolute address in the
//!process space of the current process. Never throws.*/
void * get_address_from_handle (handle_t offset) const
- { return detail::char_ptr_cast(this->get_address()) + offset; }
+ { return reinterpret_cast<char*>(this->get_address()) + offset; }
//!Searches for nbytes of free memory in the segment, marks the
//!memory as used and return the pointer to the memory. If no
Modified: trunk/boost/interprocess/detail/managed_multi_shared_memory.hpp
==============================================================================
--- trunk/boost/interprocess/detail/managed_multi_shared_memory.hpp (original)
+++ trunk/boost/interprocess/detail/managed_multi_shared_memory.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -117,7 +117,7 @@
shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
}
- return result_type((void *)0, 0);
+ return result_type(static_cast<void *>(0), 0);
}
virtual bool update_segments ()
@@ -169,7 +169,7 @@
//segment id = 0 of this group
void_pointer::insert_mapping
( group
- , (char*)addr - managed_impl::ManagedOpenOrCreateUserOffset
+ , static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
, size + managed_impl::ManagedOpenOrCreateUserOffset);
//Check if this is the master segment
if(!m_segment_number){
Modified: trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp
==============================================================================
--- trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp (original)
+++ trunk/boost/interprocess/detail/managed_open_or_create_impl.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -189,13 +189,13 @@
{ return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; }
void *get_user_address() const
- { return (char*)m_mapped_region.get_address() + ManagedOpenOrCreateUserOffset; }
+ { return static_cast<char*>(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset; }
std::size_t get_real_size() const
{ return m_mapped_region.get_size(); }
void *get_real_address() const
- { return (char*)m_mapped_region.get_address(); }
+ { return m_mapped_region.get_address(); }
void swap(managed_open_or_create_impl &other)
{
@@ -360,7 +360,7 @@
if(previous == UninitializedSegment){
try{
write_whole_device<FileBased>(dev, size, file_like_t());
- construct_func((char*)region.get_address() + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true);
+ construct_func(static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true);
//All ok, just move resources to the external mapped region
m_mapped_region.swap(region);
}
@@ -413,7 +413,7 @@
if(value != InitializedSegment)
throw interprocess_exception(error_info(corrupted_error));
- construct_func( (char*)region.get_address() + ManagedOpenOrCreateUserOffset
+ construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
, region.get_size() - ManagedOpenOrCreateUserOffset
, false);
//All ok, just move resources to the external mapped region
Modified: trunk/boost/interprocess/detail/move.hpp
==============================================================================
--- trunk/boost/interprocess/detail/move.hpp (original)
+++ trunk/boost/interprocess/detail/move.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -119,6 +119,18 @@
return type(object);
}
+template <class T>
+inline const T& forward_impl(const T &t)
+{ return t; }
+
+template <class T>
+inline T& forward_impl(T &t)
+{ return t; }
+
+template <class T>
+inline detail::moved_object<T> forward_impl(detail::moved_object<T> &t)
+{ return t; }
+
} //namespace detail {
//!A function that converts an object to a moved object so that
Modified: trunk/boost/interprocess/detail/named_proxy.hpp
==============================================================================
--- trunk/boost/interprocess/detail/named_proxy.hpp (original)
+++ trunk/boost/interprocess/detail/named_proxy.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -19,14 +19,16 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <new>
+#include <iterator>
#include <boost/interprocess/detail/in_place_interface.hpp>
-#include <boost/preprocessor/iteration/local.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/repetition/enum.hpp>
-#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/interprocess/detail/mpl.hpp>
-#include <iterator>
+
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#else
+#include <boost/interprocess/detail/move.hpp>
+#include <boost/interprocess/detail/variadic_templates_tools.hpp>
+#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
//!\file
//!Describes a proxy class that implements named allocation syntax.
@@ -35,6 +37,101 @@
namespace interprocess {
namespace detail {
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+template<class T, bool is_iterator, class ...Args>
+struct CtorNArg : public placement_destroy<T>
+{
+ typedef detail::bool_<is_iterator> IsIterator;
+ typedef CtorNArg<T, is_iterator, Args...> self_t;
+ typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+
+ self_t& operator++()
+ {
+ this->do_increment(IsIterator(), index_tuple_t());
+ return *this;
+ }
+
+ self_t operator++(int) { return ++*this; *this; }
+
+ CtorNArg(Args && ...args)
+ : args_(args...)
+ {}
+
+ virtual void construct_n(void *mem
+ , std::size_t num
+ , std::size_t &constructed)
+ {
+ T* memory = static_cast<T*>(mem);
+ for(constructed = 0; constructed < num; ++constructed){
+ this->construct(memory++, IsIterator(), index_tuple_t());
+ this->do_increment(IsIterator(), index_tuple_t());
+ }
+ }
+
+ private:
+ template<int ...IdxPack>
+ void construct(void *mem, detail::true_, const index_tuple<IdxPack...>&)
+ { new((void*)mem)T(*detail::forward_impl<Args>(get<IdxPack>(args_))...); }
+
+ template<int ...IdxPack>
+ void construct(void *mem, detail::false_, const index_tuple<IdxPack...>&)
+ { new((void*)mem)T(detail::forward_impl<Args>(get<IdxPack>(args_))...); }
+
+ template<int ...IdxPack>
+ void do_increment(detail::true_, const index_tuple<IdxPack...>&)
+ {
+ this->expansion_helper(++get<IdxPack>(args_)...);
+ }
+
+ template<class ...ExpansionArgs>
+ void expansion_helper(ExpansionArgs &&...)
+ {}
+
+ template<int ...IdxPack>
+ void do_increment(detail::false_, const index_tuple<IdxPack...>&)
+ {}
+
+ tuple<Args&&...> args_;
+};
+
+//!Describes a proxy class that implements named
+//!allocation syntax.
+template
+ < class SegmentManager //segment manager to construct the object
+ , class T //type of object to build
+ , bool is_iterator //passing parameters are normal object or iterators?
+ >
+class named_proxy
+{
+ typedef typename SegmentManager::char_type char_type;
+ const char_type * mp_name;
+ SegmentManager * mp_mngr;
+ mutable std::size_t m_num;
+ const bool m_find;
+ const bool m_dothrow;
+
+ public:
+ named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
+ : mp_name(name), mp_mngr(mngr), m_num(1)
+ , m_find(find), m_dothrow(dothrow)
+ {}
+
+ template<class ...Args>
+ T *operator()(Args &&...args) const
+ {
+ CtorNArg<T, is_iterator, Args...> ctor_obj(detail::forward_impl<Args>(args)...);
+ return mp_mngr->template
+ generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
+ }
+
+ //This operator allows --> named_new("Name")[3]; <-- syntax
+ const named_proxy &operator[](std::size_t num) const
+ { m_num *= num; return *this; }
+};
+
+#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
//!Function object that makes placement new
//!without arguments
template<class T>
@@ -52,21 +149,18 @@
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
{
- T* memory = (T*)(mem);
+ T* memory = static_cast<T*>(mem);
for(constructed = 0; constructed < num; ++constructed)
new((void*)memory++)T;
}
};
-#ifndef BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS
-# define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
-#endif
-
////////////////////////////////////////////////////////////////
// What the macro should generate (n == 2):
//
// template<class T, bool is_iterator, class P1, class P2>
// struct Ctor2Arg
+// : public placement_destroy<T>
// {
// typedef detail::bool_<is_iterator> IsIterator;
// typedef Ctor2Arg self_t;
@@ -94,7 +188,7 @@
// , std::size_t num
// , std::size_t &constructed)
// {
-// T* memory = (T*)(mem);
+// T* memory = static_cast<T*>(mem);
// for(constructed = 0; constructed < num; ++constructed){
// this->construct(memory++, IsIterator());
// this->do_increment(IsIterator());
@@ -118,22 +212,6 @@
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
-#define BOOST_INTERPROCESS_AUX_PARAM_LIST(z, n, data) \
- const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
-//!
-
-#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
-//!
-
-#define BOOST_INTERPROCESS_AUX_PARAM_INC(z, n, data) \
- BOOST_PP_CAT(++m_p, n) \
-//!
-
-#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
- BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
-//!
-
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
@@ -156,14 +234,14 @@
self_t operator++(int) { return ++*this; *this; } \
\
BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
- ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_LIST, _) ) \
+ ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
: BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
\
virtual void construct_n(void *mem \
, std::size_t num \
, std::size_t &constructed) \
{ \
- T* memory = (T*)(mem); \
+ T* memory = static_cast<T*>(mem); \
for(constructed = 0; constructed < num; ++constructed){ \
this->construct(memory++, IsIterator()); \
this->do_increment(IsIterator()); \
@@ -172,24 +250,23 @@
\
private: \
void construct(void *mem, detail::true_) \
- { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, *m_p)); } \
+ { \
+ new((void*)mem) T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
+ } \
\
void construct(void *mem, detail::false_) \
- { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \
+ { \
+ new((void*)mem) T \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
+ } \
\
- BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
+ BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
}; \
//!
-
-
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
-#undef BOOST_INTERPROCESS_AUX_PARAM_LIST
-#undef BOOST_INTERPROCESS_AUX_PARAM_INIT
-#undef BOOST_INTERPROCESS_AUX_PARAM_DEFINE
-#undef BOOST_INTERPROCESS_AUX_PARAM_INC
-
//!Describes a proxy class that implements named
//!allocation syntax.
template
@@ -222,32 +299,22 @@
}
//!
- // Boost preprocessor used to create operator() overloads
- #define BOOST_INTERPROCESS_AUX_TYPE_LIST(z, n, data) \
- BOOST_PP_CAT(P, n) \
- //!
-
- #define BOOST_INTERPROCESS_AUX_PARAM_LIST(z, n, data) \
- const BOOST_PP_CAT(P, n) BOOST_PP_CAT(&p, n) \
- //!
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- template<BOOST_PP_ENUM_PARAMS(n, class P)> \
- T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_AUX_PARAM_LIST, _)) const \
- { \
- typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
- <T, is_iterator, BOOST_PP_ENUM (n, BOOST_INTERPROCESS_AUX_TYPE_LIST, _)> \
- ctor_obj_t; \
- ctor_obj_t ctor_obj (BOOST_PP_ENUM_PARAMS(n, p)); \
- return mp_mngr->template generic_construct<T> \
- (mp_name, m_num, m_find, m_dothrow, ctor_obj); \
- } \
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<BOOST_PP_ENUM_PARAMS(n, class P)> \
+ T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
+ { \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
+ <T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
+ ctor_obj_t; \
+ ctor_obj_t ctor_obj \
+ (BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
+ return mp_mngr->template generic_construct<T> \
+ (mp_name, m_num, m_find, m_dothrow, ctor_obj); \
+ } \
//!
#define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
#include BOOST_PP_LOCAL_ITERATE()
- #undef BOOST_INTERPROCESS_AUX_PARAM_LIST
- #undef BOOST_INTERPROCESS_AUX_TYPE_LIST
////////////////////////////////////////////////////////////////////////
// What the macro should generate (n == 2)
@@ -272,6 +339,8 @@
{ m_num *= num; return *this; }
};
+#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
}}} //namespace boost { namespace interprocess { namespace detail {
#include <boost/interprocess/detail/config_end.hpp>
Modified: trunk/boost/interprocess/detail/os_file_functions.hpp
==============================================================================
--- trunk/boost/interprocess/detail/os_file_functions.hpp (original)
+++ trunk/boost/interprocess/detail/os_file_functions.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -101,6 +101,9 @@
inline bool delete_file(const char *name)
{ return winapi::delete_file(name); }
+inline bool delete_file_on_reboot_if_possible(const char *filename)
+{ return winapi::move_file_ex(filename, 0, winapi::movefile_delay_until_reboot); }
+
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{
if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
@@ -260,6 +263,12 @@
inline bool delete_file(const char *name)
{ return ::unlink(name) == 0; }
+
+inline bool delete_file_on_reboot_if_possible(const char *)
+{ //Function not implemented in POSIX functions
+ return false;
+}
+
inline bool truncate_file (file_handle_t hnd, std::size_t size)
{ return 0 == ::ftruncate(hnd, size); }
@@ -274,11 +283,11 @@
}
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
-{ return off == lseek(hnd, off, (int)pos); }
+{ return off == ::lseek(hnd, off, (int)pos); }
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
{
- off = lseek(hnd, 0, SEEK_CUR);
+ off = ::lseek(hnd, 0, SEEK_CUR);
return off != ((off_t)-1);
}
Added: trunk/boost/interprocess/detail/preprocessor.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/preprocessor.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -0,0 +1,113 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
+#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+
+#define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
+
+//Note:
+//We define template parameters as const references to
+//be able to bind temporaries. After that we will un-const them.
+//This cast is ugly but it is necessary until "perfect forwarding"
+//is achieved in C++0x. Meanwhile, if we want to be able to
+//bind rvalues with non-const references, we have to be ugly
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
+ const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
+ //!
+#endif
+
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ #define BOOST_INTERPROCESS_PARAM(U, u) \
+ U && u \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PARAM(U, u) \
+ const U & u \
+ //!
+#endif
+
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
+//!
+#else
+#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
+//!
+#endif
+
+#define BOOST_INTERPROCESS_AUX_PARAM_INC(z, n, data) \
+ BOOST_PP_CAT(++m_p, n) \
+//!
+
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
+//!
+#else
+#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+//!
+#endif
+
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ #define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
+ detail::forward_impl< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
+ BOOST_PP_CAT(p, n) \
+ //!
+#endif
+
+#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
+ detail::forward_impl< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
+ //!
+#else
+ #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
+ BOOST_PP_CAT(m_p, n) \
+ //!
+#endif
+
+#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
+BOOST_PP_CAT(*m_p, n) \
+//!
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#else
+#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#error "This file is not needed when perfect forwarding is available"
+#endif
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
Modified: trunk/boost/interprocess/detail/segment_manager_helper.hpp
==============================================================================
--- trunk/boost/interprocess/detail/segment_manager_helper.hpp (original)
+++ trunk/boost/interprocess/detail/segment_manager_helper.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -123,8 +123,8 @@
template<class CharType>
CharType *name() const
{
- return reinterpret_cast<CharType*>
- (detail::char_ptr_cast(this) + name_offset());
+ return const_cast<CharType*>(reinterpret_cast<const CharType*>
+ (reinterpret_cast<const char*>(this) + name_offset()));
}
std::size_t name_length() const
@@ -137,7 +137,7 @@
void *value() const
{
- return detail::char_ptr_cast(this) + value_offset();
+ return const_cast<char*>((reinterpret_cast<const char*>(this) + value_offset()));
}
std::size_t value_offset() const
@@ -169,8 +169,9 @@
static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
{
block_header * hdr =
- reinterpret_cast<block_header*>(detail::char_ptr_cast(value) -
- get_rounded_size(sizeof(block_header), algn));
+ const_cast<block_header*>
+ (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
+ get_rounded_size(sizeof(block_header), algn)));
(void)sz;
//Some sanity checks
assert(hdr->m_value_alignment == algn);
@@ -182,8 +183,8 @@
static block_header *from_first_header(Header *header)
{
block_header * hdr =
- reinterpret_cast<block_header*>(detail::char_ptr_cast(header) +
- get_rounded_size(sizeof(Header), detail::alignment_of<block_header>::value));
+ reinterpret_cast<block_header*>(reinterpret_cast<char*>(header) +
+ get_rounded_size(sizeof(Header), detail::alignment_of<block_header>::value));
//Some sanity checks
return hdr;
}
@@ -192,7 +193,7 @@
static Header *to_first_header(block_header *bheader)
{
Header * hdr =
- reinterpret_cast<Header*>(detail::char_ptr_cast(bheader) -
+ reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
get_rounded_size(sizeof(Header), detail::alignment_of<block_header>::value));
//Some sanity checks
return hdr;
@@ -269,8 +270,9 @@
block_header *get_block_header() const
{
- return (block_header *)(detail::char_ptr_cast(this) +
- get_rounded_size(sizeof(*this), BlockHdrAlignment));
+ return const_cast<block_header*>
+ (reinterpret_cast<const block_header *>(reinterpret_cast<const char*>(this) +
+ get_rounded_size(sizeof(*this), BlockHdrAlignment)));
}
bool operator <(const intrusive_value_type_impl<Hook, CharType> & other) const
@@ -281,7 +283,7 @@
static intrusive_value_type_impl *get_intrusive_value_type(block_header *hdr)
{
- return (intrusive_value_type_impl *)(detail::char_ptr_cast(hdr) -
+ return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
get_rounded_size(sizeof(intrusive_value_type_impl), BlockHdrAlignment));
}
@@ -304,11 +306,11 @@
{}
char_ptr_holder(const detail::anonymous_instance_t *)
- : m_name((CharType*)0)
+ : m_name(static_cast<CharType*>(0))
{}
char_ptr_holder(const detail::unique_instance_t *)
- : m_name((CharType*)-1)
+ : m_name(reinterpret_cast<CharType*>(-1))
{}
operator const CharType *()
@@ -380,7 +382,7 @@
index_data(void *ptr) : m_ptr(ptr){}
void *value() const
- { return (void*)detail::get_pointer(m_ptr); }
+ { return static_cast<void>(detail::get_pointer(m_ptr)); }
};
template<class MemoryAlgorithm>
Modified: trunk/boost/interprocess/detail/type_traits.hpp
==============================================================================
--- trunk/boost/interprocess/detail/type_traits.hpp (original)
+++ trunk/boost/interprocess/detail/type_traits.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -128,6 +128,15 @@
{
typedef const nat& type;
};
+
+template <class T>
+struct add_const_reference
+{ typedef const T &type; };
+
+template <class T>
+struct add_const_reference<T&>
+{ typedef T& type; };
+
template <typename T, typename U>
struct is_same
{
@@ -146,38 +155,6 @@
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
};
-/*
-template <template<class P> typename T, template<typename P2> typename U>
-struct is_same
-{
- typedef char yes_type;
- struct no_type
- {
- char padding[8];
- };
-
- template <template<class P3> typename V>
- static yes_type is_same_tester(V<P3>*, V<P3>*);
- static no_type is_same_tester(...);
-
- static T<int> *t;
- static U<int> *u;
-
- static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
-};*/
-/*
-template< typename T >
-struct is_pointer_impl
-{
- static const bool value =
- (::boost::type_traits::ice_and<
- ::boost::detail::is_pointer_helper<typename remove_cv<T>::type>::value
- , ::boost::type_traits::ice_not<
- ::boost::is_member_pointer<T>::value
- >::value
- >::value)
- );
-};*/
} // namespace detail
} //namespace interprocess {
Modified: trunk/boost/interprocess/detail/utilities.hpp
==============================================================================
--- trunk/boost/interprocess/detail/utilities.hpp (original)
+++ trunk/boost/interprocess/detail/utilities.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -28,6 +28,9 @@
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/version_type.hpp>
+#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
+#include <boost/interprocess/detail/preprocessor.hpp>
+#endif
#include <utility>
#include <algorithm>
@@ -115,6 +118,9 @@
void priv_deallocate(allocator_v2)
{ m_alloc.deallocate_one(m_ptr); }
+ scoped_deallocator(const scoped_deallocator &);
+ scoped_deallocator& operator=(const scoped_deallocator &);
+
public:
pointer m_ptr;
Allocator& m_alloc;
@@ -125,10 +131,36 @@
~scoped_deallocator()
{ if (m_ptr)priv_deallocate(alloc_version()); }
+ #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ scoped_deallocator(scoped_deallocator &&o)
+ : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
+ {
+ #else
+ scoped_deallocator(moved_object<scoped_deallocator> mo)
+ : m_ptr(mo.get().m_ptr), m_alloc(mo.get().m_alloc)
+ {
+ scoped_deallocator &o = mo.get();
+ #endif
+ o.release();
+ }
+
+ pointer get() const
+ { return m_ptr; }
+
void release()
{ m_ptr = 0; }
};
+} //namespace detail {
+
+template <class Allocator>
+struct is_movable<boost::interprocess::detail::scoped_deallocator<Allocator> >
+{
+ static const bool value = true;
+};
+
+namespace detail {
+
//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
@@ -353,20 +385,6 @@
{ m_itbeg = multiallocation_iterator(); }
};
-//!Forces a cast from any pointer to char *pointer
-template<class T>
-inline char* char_ptr_cast(T *ptr)
-{
- //This is nasty, but we like it a lot!
- return (char*)(ptr);
-}
-
-inline char* char_ptr_cast()
-{
- //This is nasty, but we like it a lot!
- return (char*)(0);
-}
-
//Rounds "orig_size" by excess to round_to bytes
inline std::size_t get_rounded_size(std::size_t orig_size, std::size_t round_to)
{
@@ -510,19 +528,18 @@
T1 first;
T2 second;
- pair()
- : first(), second()
- {}
-
- pair(const T1& x, const T2& y)
- : first(x), second(y)
- {}
-
+ //std::pair compatibility
template <class D, class S>
pair(const std::pair<D, S>& p)
: first(p.first), second(p.second)
{}
+ //To resolve ambiguity with the variadic constructor of 1 argument
+ //and the previous constructor
+ pair(std::pair<T1, T2>& x)
+ : first(x.first), second(x.second)
+ {}
+
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
pair(const detail::moved_object<std::pair<D, S> >& p)
@@ -535,49 +552,78 @@
{}
#endif
+ pair()
+ : first(), second()
+ {}
+
+ pair(const pair<T1, T2>& x)
+ : first(x.first), second(x.second)
+ {}
+
+ //To resolve ambiguity with the variadic constructor of 1 argument
+ //and the copy constructor
+ pair(pair<T1, T2>& x)
+ : first(x.first), second(x.second)
+ {}
+
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template <class D, class S>
- pair(const detail::moved_object<pair<D, S> >& p)
+ pair(const detail::moved_object<pair<T1, T2> >& p)
: first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
{}
#else
- template <class D, class S>
- pair(pair<D, S> && p)
+ pair(pair<T1, T2> && p)
: first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
{}
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- template <class U, class V>
- pair(const detail::moved_object<U> &x, const detail::moved_object<V> &y)
- : first(detail::move_impl(x.get())), second(detail::move_impl(y.get()))
+ template <class D, class S>
+ pair(const detail::moved_object<pair<D, S> >& p)
+ : first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
{}
#else
- template <class U, class V>
- pair(U &&x, V &&y)
- : first(detail::move_impl(x)), second(detail::move_impl(y))
+ template <class D, class S>
+ pair(pair<D, S> && p)
+ : first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
{}
#endif
- #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- pair(const detail::moved_object<pair> &p)
- : first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second))
+ #ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
+
+ template<class U, class ...Args>
+ pair(U &&u, Args &&... args)
+ : first(detail::forward_impl<U>(u))
+ , second(detail::forward_impl<Args>(args)...)
{}
+
#else
- pair(pair &&p)
- : first(detail::move_impl(p.first)), second(detail::move_impl(p.second))
- {}
+
+ template<class U>
+ pair(BOOST_INTERPROCESS_PARAM(U, u))
+ : first(detail::forward_impl<U>(u))
+ {}
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \
+ pair(BOOST_INTERPROCESS_PARAM(U, u) \
+ ,BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) \
+ : first(detail::forward_impl<U>(u)) \
+ , second(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)) \
+ {} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
#endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
- pair& operator=(const detail::moved_object<pair> &p)
+ pair& operator=(const detail::moved_object<pair<T1, T2> > &p)
{
first = detail::move_impl(p.get().first);
second = detail::move_impl(p.get().second);
return *this;
}
#else
- pair& operator=(pair &&p)
+ pair& operator=(pair<T1, T2> &&p)
{
first = detail::move_impl(p.first);
second = detail::move_impl(p.second);
@@ -585,12 +631,21 @@
}
#endif
- pair& operator=(const pair &p)
+ #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
+ pair& operator=(const detail::moved_object<std::pair<T1, T2> > &p)
+ {
+ first = detail::move_impl(p.get().first);
+ second = detail::move_impl(p.get().second);
+ return *this;
+ }
+ #else
+ pair& operator=(std::pair<T1, T2> &&p)
{
- first = p.first;
- second = p.second;
+ first = detail::move_impl(p.first);
+ second = detail::move_impl(p.second);
return *this;
}
+ #endif
#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE
template <class D, class S>
@@ -737,6 +792,16 @@
{ return chain_.size(); }
};
+template<class T>
+struct value_init
+{
+ value_init()
+ : m_t()
+ {}
+
+ T m_t;
+};
+
} //namespace detail {
//!The pair is movable if any of its members is movable
Added: trunk/boost/interprocess/detail/variadic_templates_tools.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/variadic_templates_tools.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -0,0 +1,153 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
+#include <cstddef> //std::size_t
+
+namespace boost {
+namespace interprocess {
+namespace detail {
+
+template<typename... Values>
+class tuple;
+
+template<> class tuple<>
+{};
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+ : private tuple<Tail...>
+{
+ typedef tuple<Tail...> inherited;
+
+ public:
+ tuple() { }
+
+ // implicit copy-constructor is okay
+ // Construct tuple from separate arguments.
+ tuple(typename add_const_reference<Head>::type v,
+ typename add_const_reference<Tail>::type... vtail)
+ : inherited(vtail...), m_head(v)
+ {}
+
+ // Construct tuple from another tuple.
+ template<typename... VValues>
+ tuple(const tuple<VValues...>& other)
+ : m_head(other.head()), inherited(other.tail())
+ {}
+
+ template<typename... VValues>
+ tuple& operator=(const tuple<VValues...>& other)
+ {
+ m_head = other.head();
+ tail() = other.tail();
+ return this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+ protected:
+ Head m_head;
+};
+
+
+template<typename... Values>
+tuple<Values&&...> tie_forward(Values&&... values)
+{ return tuple<Values&&...>(values...); }
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+
+ public:
+ typedef typename add_reference<Element>::type type;
+ typedef typename add_const_reference<Element>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+ static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+ public:
+ typedef typename add_reference<Head>::type type;
+ typedef typename add_const_reference<Head>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return t.head(); }
+ static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
+};
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+////////////////////////////////////////////////////
+// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
+// be used to "unpack" into comma-separated values
+// in a function call.
+////////////////////////////////////////////////////
+
+template<int... Indexes>
+struct index_tuple{};
+
+template<std::size_t Num, typename Tuple = index_tuple<> >
+struct build_number_seq;
+
+template<std::size_t Num, int... Indexes>
+struct build_number_seq<Num, index_tuple<Indexes...> >
+ : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
+{};
+
+template<int... Indexes>
+struct build_number_seq<0, index_tuple<Indexes...> >
+{ typedef index_tuple<Indexes...> type; };
+
+
+}}} //namespace boost { namespace interprocess { namespace detail {
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
Modified: trunk/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- trunk/boost/interprocess/detail/win32_api.hpp (original)
+++ trunk/boost/interprocess/detail/win32_api.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -63,6 +63,13 @@
static const unsigned long file_map_read = section_map_read;
static const unsigned long file_map_all_access = section_all_access;
+static const unsigned long movefile_copy_allowed = 0x02;
+static const unsigned long movefile_delay_until_reboot = 0x04;
+static const unsigned long movefile_replace_existing = 0x01;
+static const unsigned long movefile_write_through = 0x08;
+static const unsigned long movefile_create_hardlink = 0x10;
+static const unsigned long movefile_fail_if_not_trackable = 0x20;
+
static const unsigned long file_share_read = 0x00000001;
static const unsigned long file_share_write = 0x00000002;
static const unsigned long file_share_delete = 0x00000004;
@@ -95,7 +102,7 @@
static const unsigned long lang_neutral = (unsigned long)0x00;
static const unsigned long sublang_default = (unsigned long)0x01;
static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF;
-static void * const invalid_handle_value = (void*)(long*)-1;
+static void * const invalid_handle_value = (void*)(long)(-1);
static const unsigned long create_new = 1;
static const unsigned long create_always = 2;
static const unsigned long open_existing = 3;
@@ -228,6 +235,7 @@
extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *);
extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *);
+extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long);
extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
@@ -361,6 +369,9 @@
static inline bool delete_file(const char *name)
{ return 0 != DeleteFileA(name); }
+static inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags)
+{ return 0 != MoveFileExA(source_filename, destination_filename, flags); }
+
static inline void get_system_info(system_info *info)
{ GetSystemInfo(info); }
@@ -401,10 +412,10 @@
{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(addr, val1, val2); }
static inline long interlocked_exchange_add(long volatile* addend, long value)
-{ return BOOST_INTERLOCKED_EXCHANGE_ADD((long*)addend, value); }
+{ return BOOST_INTERLOCKED_EXCHANGE_ADD(const_cast<long*>(addend), value); }
static inline long interlocked_exchange(long volatile* addend, long value)
-{ return BOOST_INTERLOCKED_EXCHANGE((long*)addend, value); }
+{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
} //namespace winapi
} //namespace interprocess
Modified: trunk/boost/interprocess/errors.hpp
==============================================================================
--- trunk/boost/interprocess/errors.hpp (original)
+++ trunk/boost/interprocess/errors.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -71,7 +71,7 @@
0,
sys_err_code,
winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language
- (char *) &lpMsgBuf,
+ reinterpret_cast<char *>(&lpMsgBuf),
0,
0
);
Modified: trunk/boost/interprocess/file_mapping.hpp
==============================================================================
--- trunk/boost/interprocess/file_mapping.hpp (original)
+++ trunk/boost/interprocess/file_mapping.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -181,7 +181,7 @@
///@endcond
-//!A class that stores the name of a a file
+//!A class that stores the name of a file
//!and call std::remove(name) in its destructor
//!Useful to remove temporary files in the presence
//!of exceptions
Modified: trunk/boost/interprocess/interprocess_fwd.hpp
==============================================================================
--- trunk/boost/interprocess/interprocess_fwd.hpp (original)
+++ trunk/boost/interprocess/interprocess_fwd.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -391,6 +391,11 @@
,class A = std::allocator<T> >
class vector;
+//vector class
+template <class T
+,class A = std::allocator<T> >
+class deque;
+
//list class
template <class T
,class A = std::allocator<T> >
Modified: trunk/boost/interprocess/ipc/message_queue.hpp
==============================================================================
--- trunk/boost/interprocess/ipc/message_queue.hpp (original)
+++ trunk/boost/interprocess/ipc/message_queue.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -52,7 +52,7 @@
//!Creates a process shared message queue with name "name". For this message queue,
//!the maximum number of messages will be "max_num_msg" and the maximum message size
- //!will be "max_msg_size".
+ //!will be "max_msg_size". Throws on error and if the queue was previously created.
message_queue(create_only_t create_only,
const char *name,
std::size_t max_num_msg,
@@ -62,15 +62,15 @@
//!If the queue is created, the maximum number of messages will be "max_num_msg"
//!and the maximum message size will be "max_msg_size". If queue was previously
//!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
- //!are ignored.
+ //!are ignored. Throws on error.
message_queue(open_or_create_t open_or_create,
const char *name,
std::size_t max_num_msg,
std::size_t max_msg_size);
//!Opens a previously created process shared message queue with name "name".
- //!If the was not previously created or there are no free resources, the
- //!function returns false.
+ //!If the was not previously created or there are no free resources,
+ //!throws an error.
message_queue(open_only_t open_only,
const char *name);
@@ -302,11 +302,11 @@
//Pointer to the index
msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*>
- (detail::char_ptr_cast(this)+r_hdr_size);
+ (reinterpret_cast<char*>(this)+r_hdr_size);
//Pointer to the first message header
detail::msg_hdr_t *msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
- (detail::char_ptr_cast(this)+r_hdr_size+r_index_size);
+ (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
//Initialize the pointer to the index
mp_index = index;
@@ -315,7 +315,7 @@
for(std::size_t i = 0; i < m_max_num_msg; ++i){
index[i] = msg_hdr;
msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
- (detail::char_ptr_cast(msg_hdr)+r_max_msg_size);
+ (reinterpret_cast<char*>(msg_hdr)+r_max_msg_size);
}
}
@@ -385,7 +385,7 @@
name,
get_mem_size(max_msg_size, max_num_msg),
read_write,
- (void*)0,
+ static_cast<void*>(0),
//Prepare initialization functor
detail::initialization_func_t (max_num_msg, max_msg_size))
{}
@@ -399,7 +399,7 @@
name,
get_mem_size(max_msg_size, max_num_msg),
read_write,
- (void*)0,
+ static_cast<void*>(0),
//Prepare initialization functor
detail::initialization_func_t (max_num_msg, max_msg_size))
{}
@@ -410,7 +410,7 @@
: m_shmem(open_only,
name,
read_write,
- (void*)0,
+ static_cast<void*>(0),
//Prepare initialization functor
detail::initialization_func_t ())
{}
@@ -426,7 +426,13 @@
inline bool message_queue::timed_send
(const void *buffer, std::size_t buffer_size
,unsigned int priority, const boost::posix_time::ptime &abs_time)
-{ return this->do_send(timed, buffer, buffer_size, priority, abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->send(buffer, buffer_size, priority);
+ return true;
+ }
+ return this->do_send(timed, buffer, buffer_size, priority, abs_time);
+}
inline bool message_queue::do_send(block_t block,
const void *buffer, std::size_t buffer_size,
@@ -508,7 +514,13 @@
message_queue::timed_receive(void *buffer, std::size_t buffer_size,
std::size_t &recvd_size, unsigned int &priority,
const boost::posix_time::ptime &abs_time)
-{ return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->receive(buffer, buffer_size, recvd_size, priority);
+ return true;
+ }
+ return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
+}
inline bool
message_queue::do_receive(block_t block,
Modified: trunk/boost/interprocess/mapped_region.hpp
==============================================================================
--- trunk/boost/interprocess/mapped_region.hpp (original)
+++ trunk/boost/interprocess/mapped_region.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -109,7 +109,7 @@
//!mapped memory. Never throws.
offset_t get_offset() const;
- //!Returns the mode of the mapping used to contruct the mapped file.
+ //!Returns the mode of the mapping used to construct the mapped file.
//!Never throws.
mode_t get_mode() const;
@@ -327,7 +327,7 @@
foffset_high,
foffset_low,
m_size ? static_cast<std::size_t>(m_extra_offset + m_size) : 0,
- (void*)address);
+ const_cast<void*>(address));
if(!mhandle.is_shm){
//For files we don't need the file mapping anymore
@@ -482,8 +482,7 @@
}
//Map it to the address space
-// m_base = mmap64( (void*)address
- m_base = mmap ( (void*)address
+ m_base = mmap ( const_cast<void*>(address)
, static_cast<std::size_t>(m_extra_offset + m_size)
, prot
, flags
@@ -498,13 +497,13 @@
}
//Calculate new base for the user
- void *old_base = m_base;
+ const void *old_base = m_base;
m_base = static_cast<char*>(m_base) + m_extra_offset;
m_offset = offset;
m_size = size;
//Check for fixed mapping error
- if(address && (old_base != (void*)address)){
+ if(address && (old_base != address)){
error_info err = system_error_code();
this->priv_close();
throw interprocess_exception(err);
Modified: trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -95,7 +95,7 @@
{ return !operator== (other); }
reference operator*() const
- { return *((char*)detail::get_pointer(next_alloc_.next_)); }
+ { return *reinterpret_cast<char*>(detail::get_pointer(next_alloc_.next_)); }
operator unspecified_bool_type() const
{ return next_alloc_.next_? &basic_multiallocation_iterator::unspecified_bool_type_func : 0; }
@@ -113,6 +113,9 @@
return it;
}
+ multi_allocation_next<VoidPointer> &get_multi_allocation_next()
+ { return *next_alloc_.next_; }
+
private:
multi_allocation_next<VoidPointer> next_alloc_;
};
@@ -170,7 +173,7 @@
this->last_mem_ = tmp_mem;
}
else{
- next_impl_t * old_first = (next_impl_t*)(&*this->it_);
+ next_impl_t * old_first = &this->it_.get_multi_allocation_next();
tmp_mem->next_ = old_first;
this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
}
@@ -197,7 +200,7 @@
}
else{
static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_
- = (next_impl_t*)&*other_chain.it_;
+ = &other_chain.it_.get_multi_allocation_next();
this->last_mem_ = other_chain.last_mem_;
this->num_mem_ += other_chain.num_mem_;
}
@@ -438,8 +441,8 @@
max_value(ceil_units(nbytes) + AllocatedCtrlUnits, std::size_t(MinBlockUnits));
//We can create a new block in the end of the segment
if(old_size >= (first_min_units + MinBlockUnits)){
- //block_ctrl *second = new((char*)first + Alignment*first_min_units) block_ctrl;
- block_ctrl *second = (block_ctrl *)((char*)first + Alignment*first_min_units);
+ block_ctrl *second = reinterpret_cast<block_ctrl *>
+ (reinterpret_cast<char*>(first) + Alignment*first_min_units);
first->m_size = first_min_units;
second->m_size = old_size - first->m_size;
BOOST_ASSERT(second->m_size >= MinBlockUnits);
@@ -458,8 +461,8 @@
// -----------------------------------------------------
// | MBU +more | ACB |
// -----------------------------------------------------
- char *pos = (char*)
- ((std::size_t)((char*)buffer +
+ char *pos = reinterpret_cast<char*>
+ (reinterpret_cast<std::size_t>(static_cast<char*>(buffer) +
//This is the minimum size of (2)
(MinBlockUnits*Alignment - AllocatedCtrlBytes) +
//This is the next MBU for the aligned memory
@@ -470,12 +473,13 @@
//Now obtain the address of the blocks
block_ctrl *first = memory_algo->priv_get_block(buffer);
block_ctrl *second = memory_algo->priv_get_block(pos);
- assert(pos <= ((char*)first + first->m_size*Alignment));
+ assert(pos <= (reinterpret_cast<char*>(first) + first->m_size*Alignment));
assert(first->m_size >= 2*MinBlockUnits);
- assert((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <= ((char*)first + first->m_size*Alignment));
+ assert((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <=
+ (reinterpret_cast<char*>(first) + first->m_size*Alignment));
//Set the new size of the first block
std::size_t old_size = first->m_size;
- first->m_size = ((char*)second - (char*)first)/Alignment;
+ first->m_size = (reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment;
memory_algo->priv_mark_new_allocated_block(first);
//Now check if we can create a new buffer in the end
@@ -494,7 +498,7 @@
//Check if we can create a new block (of size MinBlockUnits) in the end of the segment
if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){
//Now obtain the address of the end block
- block_ctrl *third = new ((char*)second + Alignment*second_min_units)block_ctrl;
+ block_ctrl *third = new (reinterpret_cast<char*>(second) + Alignment*second_min_units)block_ctrl;
second->m_size = second_min_units;
third->m_size = old_size - first->m_size - second->m_size;
BOOST_ASSERT(third->m_size >= MinBlockUnits);
@@ -591,10 +595,8 @@
BOOST_ASSERT(block->m_size >= BlockCtrlUnits);
//We create the new block
-// block_ctrl *new_block = new(reinterpret_cast<block_ctrl*>
-// (detail::char_ptr_cast(block) + block->m_size*Alignment)) block_ctrl;
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + block->m_size*Alignment);
+ (reinterpret_cast<char*>(block) + block->m_size*Alignment);
//Write control data to simulate this new block was previously allocated
//and deallocate it
new_block->m_size = old_block_units - block->m_size;
@@ -650,7 +652,7 @@
block_ctrl *block = memory_algo->priv_get_block(ret.first);
std::size_t received_units = block->m_size;
- char *block_address = (char*)block;
+ char *block_address = reinterpret_cast<char*>(block);
std::size_t total_used_units = 0;
// block_ctrl *prev_block = 0;
@@ -663,10 +665,7 @@
break;
total_request_units -= elem_units;
//This is the position where the new block must be created
-// if(prev_block)
-// memory_algo->priv_mark_new_allocated_block(prev_block);
- block_ctrl *new_block = (block_ctrl *)(block_address);
-// block_ctrl *new_block = new(block_address)block_ctrl;
+ block_ctrl *new_block = reinterpret_cast<block_ctrl *>(block_address);
assert_alignment(new_block);
//The last block should take all the remaining space
Modified: trunk/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -88,13 +88,13 @@
static block_ctrl *get_block_from_addr(void *addr)
{
return reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(addr) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(addr) - BlockCtrlBytes);
}
void *get_addr() const
{
return reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + BlockCtrlBytes);
+ (reinterpret_cast<const char*>(this) + BlockCtrlBytes);
}
};
@@ -235,7 +235,7 @@
//Initialize pointers
std::size_t block1_off = detail::get_rounded_size(sizeof(*this)+extra_hdr_bytes, Alignment);
m_header.m_root.m_next = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + block1_off);
+ (reinterpret_cast<char*>(this) + block1_off);
m_header.m_root.m_next->m_size = (size - block1_off)/Alignment;
m_header.m_root.m_next->m_next = &m_header.m_root;
}
@@ -264,12 +264,12 @@
//We'll create a new free block with extra_size bytes
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + old_end);
+ (reinterpret_cast<char*>(this) + old_end);
new_block->m_next = 0;
new_block->m_size = (m_header.m_size - old_end)/Alignment;
m_header.m_allocated += new_block->m_size*Alignment;
- this->priv_deallocate(detail::char_ptr_cast(new_block) + BlockCtrlBytes);
+ this->priv_deallocate(reinterpret_cast<char*>(new_block) + BlockCtrlBytes);
}
template<class MutexFamily, class VoidPointer>
@@ -286,7 +286,7 @@
//Simulate this block was previously allocated
m_header.m_allocated += new_block->m_size*Alignment;
//Return block and insert it in the free block list
- this->priv_deallocate(detail::char_ptr_cast(new_block) + BlockCtrlBytes);
+ this->priv_deallocate(reinterpret_cast<char*>(new_block) + BlockCtrlBytes);
}
template<class MutexFamily, class VoidPointer>
@@ -324,7 +324,7 @@
//Iterate through all free portions
do{
//Just clear user the memory part reserved for the user
- std::memset( detail::char_ptr_cast(block) + BlockCtrlBytes
+ std::memset( reinterpret_cast<char*>(block) + BlockCtrlBytes
, 0
, block->m_size*Alignment - BlockCtrlBytes);
block = detail::get_pointer(block->m_next);
@@ -412,7 +412,7 @@
//to be modified
//Obtain the real size of the block
block_ctrl *block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(ptr) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(ptr) - BlockCtrlBytes);
return block->m_size*Alignment - BlockCtrlBytes;
}
@@ -505,7 +505,7 @@
//We need a minimum size to split the previous one
if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){
block_ctrl *new_block = reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(reuse) - needs_backwards - BlockCtrlBytes);
+ (reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes);
new_block->m_next = 0;
new_block->m_size =
BlockCtrlSize + (needs_backwards + extra_forward)/Alignment;
@@ -615,10 +615,10 @@
{
//Take the address where the next block should go
block_ctrl *next_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment);
+ (reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment);
//Check if the adjacent block is in the managed segment
- std::size_t distance = (detail::char_ptr_cast(next_block) - detail::char_ptr_cast(this))/Alignment;
+ std::size_t distance = (reinterpret_cast<char*>(next_block) - reinterpret_cast<char*>(this))/Alignment;
if(distance >= (m_header.m_size/Alignment)){
//"next_block" does not exist so we can't expand "block"
return 0;
@@ -643,8 +643,8 @@
block_ctrl *root = &m_header.m_root;
block_ctrl *prev_2_block = root;
block_ctrl *prev_block = detail::get_pointer(root->m_next);
- while((detail::char_ptr_cast(prev_block) + prev_block->m_size*Alignment)
- != (detail::char_ptr_cast(ptr))
+ while((reinterpret_cast<char*>(prev_block) + prev_block->m_size*Alignment)
+ != (reinterpret_cast<char*>(ptr))
&& prev_block != root){
prev_2_block = prev_block;
prev_block = detail::get_pointer(prev_block->m_next);
@@ -654,7 +654,7 @@
return prev_pair_t(0, 0);
//Check if the previous block is in the managed segment
- std::size_t distance = (detail::char_ptr_cast(prev_block) - detail::char_ptr_cast(this))/Alignment;
+ std::size_t distance = (reinterpret_cast<char*>(prev_block) - reinterpret_cast<char*>(this))/Alignment;
if(distance >= (m_header.m_size/Alignment)){
//"previous_block" does not exist so we can't expand "block"
return prev_pair_t(0, 0);
@@ -672,7 +672,7 @@
{
//Obtain the real size of the block
block_ctrl *block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(ptr) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(ptr) - BlockCtrlBytes);
std::size_t old_block_size = block->m_size;
//All used blocks' next is marked with 0 so check it
@@ -747,7 +747,7 @@
{
//Obtain the real size of the block
block_ctrl *block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(ptr) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(ptr) - BlockCtrlBytes);
std::size_t block_size = block->m_size;
//All used blocks' next is marked with 0 so check it
@@ -785,14 +785,14 @@
//We create the new block
block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + block->m_size*Alignment);
+ (reinterpret_cast<char*>(block) + block->m_size*Alignment);
//Write control data to simulate this new block was previously allocated
block->m_next = 0;
block->m_size = data_size - preferred_size;
//Now deallocate the new block to insert it in the free list
- this->priv_deallocate(detail::char_ptr_cast(block)+BlockCtrlBytes);
+ this->priv_deallocate(reinterpret_cast<char*>(block)+BlockCtrlBytes);
return true;
}
@@ -820,30 +820,28 @@
else if ((((std::size_t)(buffer)) % alignment) == 0)
return buffer;
- char *aligned_portion = (char*)
- ((std::size_t)((char*)buffer + alignment - 1) & -alignment);
+ char *aligned_portion = reinterpret_cast<char*>
+ (reinterpret_cast<std::size_t>(static_cast<char*>(buffer) + alignment - 1) & -alignment);
- char *pos = ((aligned_portion - (char*)buffer) >= (MinBlockSize*Alignment)) ?
+ char *pos = ((aligned_portion - reinterpret_cast<char*>(buffer)) >= (MinBlockSize*Alignment)) ?
aligned_portion : (aligned_portion + alignment);
-
block_ctrl *first = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(buffer) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(buffer) - BlockCtrlBytes);
- block_ctrl *second = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(pos) - BlockCtrlBytes);
+ block_ctrl *second = reinterpret_cast<block_ctrl*>(pos - BlockCtrlBytes);
std::size_t old_size = first->m_size;
- first->m_size = ((char*)second - (char*)first)/Alignment;
+ first->m_size = (reinterpret_cast<char*>(second) - reinterpret_cast<char*>(first))/Alignment;
second->m_size = old_size - first->m_size;
//Write control data to simulate this new block was previously allocated
second->m_next = 0;
//Now deallocate the new block to insert it in the free list
- this->priv_deallocate(detail::char_ptr_cast(first) + BlockCtrlBytes);
- return detail::char_ptr_cast(second) + BlockCtrlBytes;
+ this->priv_deallocate(reinterpret_cast<char*>(first) + BlockCtrlBytes);
+ return reinterpret_cast<char*>(second) + BlockCtrlBytes;
}
template<class MutexFamily, class VoidPointer> inline
@@ -863,7 +861,7 @@
std::size_t total_size = block->m_size;
block->m_size = nunits;
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + Alignment*nunits);
+ (reinterpret_cast<char*>(block) + Alignment*nunits);
new_block->m_size = total_size - nunits;
new_block->m_next = block->m_next;
prev->m_next = new_block;
@@ -884,9 +882,9 @@
//Mark the block as allocated
block->m_next = 0;
//Check alignment
- assert(((detail::char_ptr_cast(block) - detail::char_ptr_cast(this))
+ assert(((reinterpret_cast<char*>(block) - reinterpret_cast<char*>(this))
% Alignment) == 0 );
- return detail::char_ptr_cast(block)+BlockCtrlBytes;
+ return reinterpret_cast<char*>(block) + BlockCtrlBytes;
}
return 0;
}
@@ -913,13 +911,13 @@
block_ctrl_ptr prev = &m_header.m_root;
block_ctrl_ptr pos = m_header.m_root.m_next;
block_ctrl_ptr block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(addr) - BlockCtrlBytes);
+ (reinterpret_cast<char*>(addr) - BlockCtrlBytes);
//All used blocks' next is marked with 0 so check it
assert(block->m_next == 0);
//Check if alignment and block size are right
- assert((detail::char_ptr_cast(addr) - detail::char_ptr_cast(this))
+ assert((reinterpret_cast<char*>(addr) - reinterpret_cast<char*>(this))
% Alignment == 0 );
std::size_t total_size = Alignment*block->m_size;
@@ -938,9 +936,9 @@
}
//Try to combine with upper block
- if ((detail::char_ptr_cast(detail::get_pointer(block))
+ if ((reinterpret_cast<char*>(detail::get_pointer(block))
+ Alignment*block->m_size) ==
- detail::char_ptr_cast(detail::get_pointer(pos))){
+ reinterpret_cast<char*>(detail::get_pointer(pos))){
block->m_size += pos->m_size;
block->m_next = pos->m_next;
@@ -950,9 +948,9 @@
}
//Try to combine with lower block
- if ((detail::char_ptr_cast(detail::get_pointer(prev))
+ if ((reinterpret_cast<char*>(detail::get_pointer(prev))
+ Alignment*prev->m_size) ==
- detail::char_ptr_cast(detail::get_pointer(block))){
+ reinterpret_cast<char*>(detail::get_pointer(block))){
prev->m_size += block->m_size;
prev->m_next = block->m_next;
}
Modified: trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -313,8 +313,9 @@
//Initialize pointers
std::size_t block1_off = priv_first_block_offset(this, extra_hdr_bytes);
+
m_header.m_root.m_next = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + block1_off);
+ ((reinterpret_cast<char*>(this) + block1_off));
algo_impl_t::assert_alignment(detail::get_pointer(m_header.m_root.m_next));
m_header.m_root.m_next->m_size = (size - block1_off)/Alignment;
m_header.m_root.m_next->m_next = &m_header.m_root;
@@ -343,8 +344,9 @@
}
//We'll create a new free block with extra_size bytes
+
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + old_end);
+ (reinterpret_cast<char*>(this) + old_end);
algo_impl_t::assert_alignment(new_block);
new_block->m_next = 0;
@@ -372,8 +374,8 @@
block = detail::get_pointer(block->m_next);
}
- char *last_free_end_address = (char*)last + last->m_size*Alignment;
- if(last_free_end_address != ((char*)this + priv_block_end_offset())){
+ char *last_free_end_address = reinterpret_cast<char*>(last) + last->m_size*Alignment;
+ if(last_free_end_address != (reinterpret_cast<char*>(this) + priv_block_end_offset())){
//there is an allocated block in the end of this block
//so no shrinking is possible
return;
@@ -388,7 +390,7 @@
if(!unique_block)
return;
last = detail::get_pointer(m_header.m_root.m_next);
- assert(last_free_end_address == ((char*)last + last->m_size*Alignment));
+ assert(last_free_end_address == (reinterpret_cast<char*>(last) + last->m_size*Alignment));
}
std::size_t last_units = last->m_size;
@@ -420,14 +422,17 @@
typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *
simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_get_block(const void *ptr)
{
- return reinterpret_cast<block_ctrl*>(detail::char_ptr_cast(ptr) - AllocatedCtrlBytes);
+ return const_cast<block_ctrl*>(reinterpret_cast<const block_ctrl*>
+ (reinterpret_cast<const char*>(ptr) - AllocatedCtrlBytes));
}
template<class MutexFamily, class VoidPointer>
inline
void *simple_seq_fit_impl<MutexFamily, VoidPointer>::
priv_get_user_buffer(const typename simple_seq_fit_impl<MutexFamily, VoidPointer>::block_ctrl *block)
-{ return detail::char_ptr_cast(block) + AllocatedCtrlBytes; }
+{
+ return const_cast<char*>(reinterpret_cast<const char*>(block) + AllocatedCtrlBytes);
+}
template<class MutexFamily, class VoidPointer>
inline void simple_seq_fit_impl<MutexFamily, VoidPointer>::priv_add_segment(void *addr, std::size_t size)
@@ -564,7 +569,7 @@
T *reuse_ptr)
{
std::pair<void*, bool> ret = priv_allocation_command
- (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T));
+ (command, limit_size, preferred_size, received_size, static_cast<void*>(reuse_ptr), sizeof(T));
BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of<T>::value));
return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second);
@@ -577,7 +582,7 @@
void *reuse_ptr, std::size_t sizeof_object)
{
if(!sizeof_object)
- return std::pair<void *, bool>((void*)0, 0);
+ return std::pair<void *, bool>(static_cast<void*>(0), 0);
if(command & try_shrink_in_place){
bool success = algo_impl_t::try_shrink
( this, reuse_ptr, limit_objects*sizeof_object
@@ -596,7 +601,7 @@
void *reuse_ptr, std::size_t sizeof_object)
{
command &= ~expand_bwd;
- if(!command) return std::pair<void *, bool>((void*)0, false);
+ if(!command) return std::pair<void *, bool>(static_cast<void*>(0), false);
std::pair<void*, bool> ret;
std::size_t max_count = m_header.m_size/sizeof_object;
@@ -623,8 +628,7 @@
//We need no synchronization since this block is not going
//to be modified
//Obtain the real size of the block
- block_ctrl *block = reinterpret_cast<block_ctrl*>
- (priv_get_block(detail::char_ptr_cast(const_cast<void*>(ptr))));
+ const block_ctrl *block = static_cast<const block_ctrl*>(priv_get_block(ptr));
return block->get_user_bytes();
}
@@ -678,8 +682,9 @@
//We need a minimum size to split the previous one
if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){
- block_ctrl *new_block = reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(reuse) - needs_backwards - BlockCtrlBytes);
+ block_ctrl *new_block = reinterpret_cast<block_ctrl*>
+ (reinterpret_cast<char*>(reuse) - needs_backwards - BlockCtrlBytes);
+
new_block->m_next = 0;
new_block->m_size =
BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment;
@@ -769,7 +774,7 @@
received_size = 0;
if(limit_size > preferred_size)
- return return_type((void*)0, false);
+ return return_type(static_cast<void*>(0), false);
//Number of units to request (including block_ctrl header)
std::size_t nunits = detail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlUnits;
@@ -819,7 +824,7 @@
if(biggest_block){
std::size_t limit_units = detail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlUnits;
if(biggest_block->m_size < limit_units)
- return return_type((void*)0, false);
+ return return_type(static_cast<void*>(0), false);
received_size = biggest_block->m_size*Alignment - BlockCtrlUnits;
void *ret = this->priv_check_and_allocate
@@ -836,7 +841,7 @@
algo_impl_t::assert_alignment(ret.first);
return ret;
}
- return return_type((void*)0, false);
+ return return_type(static_cast<void*>(0), false);
}
template<class MutexFamily, class VoidPointer> inline
@@ -852,10 +857,13 @@
{
//Take the address where the next block should go
block_ctrl *next_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment);
+ (reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment);
//Check if the adjacent block is in the managed segment
- std::size_t distance = (detail::char_ptr_cast(next_block) - detail::char_ptr_cast(this))/Alignment;
+ char *this_char_ptr = reinterpret_cast<char*>(this);
+ char *next_char_ptr = reinterpret_cast<char*>(next_block);
+ std::size_t distance = (next_char_ptr - this_char_ptr)/Alignment;
+
if(distance >= (m_header.m_size/Alignment)){
//"next_block" does not exist so we can't expand "block"
return 0;
@@ -880,21 +888,25 @@
block_ctrl *root = &m_header.m_root;
block_ctrl *prev_2_block = root;
block_ctrl *prev_block = detail::get_pointer(root->m_next);
- while((detail::char_ptr_cast(prev_block) + prev_block->m_size*Alignment)
- != (detail::char_ptr_cast(ptr))
+
+ while((reinterpret_cast<char*>(prev_block) + prev_block->m_size*Alignment)
+ != reinterpret_cast<char*>(ptr)
&& prev_block != root){
prev_2_block = prev_block;
prev_block = detail::get_pointer(prev_block->m_next);
}
if(prev_block == root || !prev_block->m_next)
- return prev_pair_t((block_ctrl*)0, (block_ctrl*)0);
+ return prev_pair_t(static_cast<block_ctrl*>(0), static_cast<block_ctrl*>(0));
//Check if the previous block is in the managed segment
- std::size_t distance = (detail::char_ptr_cast(prev_block) - detail::char_ptr_cast(this))/Alignment;
+ char *this_char_ptr = reinterpret_cast<char*>(this);
+ char *prev_char_ptr = reinterpret_cast<char*>(prev_block);
+ std::size_t distance = (prev_char_ptr - this_char_ptr)/Alignment;
+
if(distance >= (m_header.m_size/Alignment)){
//"previous_block" does not exist so we can't expand "block"
- return prev_pair_t((block_ctrl*)0, (block_ctrl*)0);
+ return prev_pair_t(static_cast<block_ctrl*>(0), static_cast<block_ctrl*>(0));
}
return prev_pair_t(prev_2_block, prev_block);
}
@@ -990,8 +1002,9 @@
//the second's size will be "block->m_size-units"
std::size_t total_size = block->m_size;
block->m_size = nunits;
+
block_ctrl *new_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + Alignment*nunits);
+ (reinterpret_cast<char*>(block) + Alignment*nunits);
new_block->m_size = total_size - nunits;
new_block->m_next = block->m_next;
prev->m_next = new_block;
@@ -1063,10 +1076,10 @@
}
//Try to combine with upper block
- if ((detail::char_ptr_cast(detail::get_pointer(block))
- + Alignment*block->m_size) ==
- detail::char_ptr_cast(detail::get_pointer(pos))){
+ char *block_char_ptr = reinterpret_cast<char*>(detail::get_pointer(block));
+ if ((block_char_ptr + Alignment*block->m_size) ==
+ reinterpret_cast<char*>(detail::get_pointer(pos))){
block->m_size += pos->m_size;
block->m_next = pos->m_next;
}
@@ -1075,9 +1088,11 @@
}
//Try to combine with lower block
- if ((detail::char_ptr_cast(detail::get_pointer(prev))
+ if ((reinterpret_cast<char*>(detail::get_pointer(prev))
+ Alignment*prev->m_size) ==
- detail::char_ptr_cast(detail::get_pointer(block))){
+ block_char_ptr){
+
+
prev->m_size += block->m_size;
prev->m_next = block->m_next;
}
Modified: trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp (original)
+++ trunk/boost/interprocess/mem_algo/rbtree_best_fit.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -331,7 +331,7 @@
;
private:
- //Due to embedded bits in size, Alignment must be at least 2
+ //Due to embedded bits in size, Alignment must be at least 4
BOOST_STATIC_ASSERT((Alignment >= 4));
//Due to rbtree size optimizations, Alignment must have at least pointer alignment
BOOST_STATIC_ASSERT((Alignment >= detail::alignment_of<void_pointer>::value));
@@ -380,7 +380,7 @@
//cover the whole segment
assert(get_min_size(extra_hdr_bytes) <= size);
std::size_t block1_off = priv_first_block_offset(this, extra_hdr_bytes);
- priv_add_segment(detail::char_ptr_cast(this) + block1_off, size - block1_off);
+ priv_add_segment(reinterpret_cast<char*>(this) + block1_off, size - block1_off);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
@@ -399,11 +399,11 @@
priv_first_block_offset(this, m_header.m_extra_hdr_bytes);
block_ctrl *first_block = reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(this) + block1_off);
+ (reinterpret_cast<char*>(this) + block1_off);
block_ctrl *old_end_block = priv_end_block(first_block);
assert(priv_is_allocated_block(old_end_block));
- std::size_t old_border_offset = (detail::char_ptr_cast(old_end_block) -
- detail::char_ptr_cast(this)) + EndCtrlBlockBytes;
+ std::size_t old_border_offset = (reinterpret_cast<char*>(old_end_block) -
+ reinterpret_cast<char*>(this)) + EndCtrlBlockBytes;
//Update managed buffer's size
m_header.m_size += extra_size;
@@ -417,9 +417,9 @@
//Now create a new block between the old end and the new end
std::size_t align_offset = (m_header.m_size - old_border_offset)/Alignment;
block_ctrl *new_end_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(old_end_block) + align_offset*Alignment);
- new_end_block->m_size = (detail::char_ptr_cast(first_block) -
- detail::char_ptr_cast(new_end_block))/Alignment;
+ (reinterpret_cast<char*>(old_end_block) + align_offset*Alignment);
+ new_end_block->m_size = (reinterpret_cast<char*>(first_block) -
+ reinterpret_cast<char*>(new_end_block))/Alignment;
first_block->m_prev_size = new_end_block->m_size;
assert(first_block == priv_next_block(new_end_block));
priv_mark_new_allocated_block(new_end_block);
@@ -428,8 +428,8 @@
//The old end block is the new block
block_ctrl *new_block = old_end_block;
- new_block->m_size = (detail::char_ptr_cast(new_end_block) -
- detail::char_ptr_cast(new_block))/Alignment;
+ new_block->m_size = (reinterpret_cast<char*>(new_end_block) -
+ reinterpret_cast<char*>(new_block))/Alignment;
assert(new_block->m_size >= BlockCtrlUnits);
priv_mark_new_allocated_block(new_block);
assert(priv_next_block(new_block) == new_end_block);
@@ -448,7 +448,7 @@
priv_first_block_offset(this, m_header.m_extra_hdr_bytes);
block_ctrl *first_block = reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(this) + block1_off);
+ (reinterpret_cast<char*>(this) + block1_off);
algo_impl_t::assert_alignment(first_block);
block_ctrl *old_end_block = priv_end_block(first_block);
@@ -485,8 +485,8 @@
//Erase block from the free tree, since we will erase it
m_header.m_imultiset.erase(Imultiset::s_iterator_to(*last_block));
- std::size_t shrunk_border_offset = (detail::char_ptr_cast(last_block) -
- detail::char_ptr_cast(this)) + EndCtrlBlockBytes;
+ std::size_t shrunk_border_offset = (reinterpret_cast<char*>(last_block) -
+ reinterpret_cast<char*>(this)) + EndCtrlBlockBytes;
block_ctrl *new_end_block = last_block;
algo_impl_t::assert_alignment(new_end_block);
@@ -521,13 +521,12 @@
//The "end" node is just a node of size 0 with the "end" bit set
block_ctrl *end_block = static_cast<block_ctrl*>
- (new (reinterpret_cast<SizeHolder*>
- (detail::char_ptr_cast(addr) + first_big_block->m_size*Alignment))SizeHolder);
+ (new (reinterpret_cast<char*>(addr) + first_big_block->m_size*Alignment)SizeHolder);
//This will overwrite the prev part of the "end" node
priv_mark_as_free_block (first_big_block);
first_big_block->m_prev_size = end_block->m_size =
- (detail::char_ptr_cast(first_big_block) - detail::char_ptr_cast(end_block))/Alignment;
+ (reinterpret_cast<char*>(first_big_block) - reinterpret_cast<char*>(end_block))/Alignment;
priv_mark_as_allocated_block(end_block);
assert(priv_next_block(first_big_block) == end_block);
@@ -539,7 +538,8 @@
//to optimize the space wasted in bookkeeping:
//Check that the sizes of the header are placed before the rbtree
- assert((void*)(SizeHolder*)first_big_block < (void*)(TreeHook*)first_big_block);
+ assert(static_cast<void*>(static_cast<SizeHolder*>(first_big_block))
+ < static_cast<void*>(static_cast<TreeHook*>(first_big_block)));
//Check that the alignment is power of two (we use some optimizations based on this)
//assert((Alignment % 2) == 0);
@@ -653,7 +653,7 @@
T *reuse_ptr)
{
std::pair<void*, bool> ret = priv_allocation_command
- (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T));
+ (command, limit_size, preferred_size, received_size, static_cast<void*>(reuse_ptr), sizeof(T));
BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of<T>::value));
return std::pair<T *, bool>(static_cast<T*>(ret.first), ret.second);
@@ -666,7 +666,7 @@
void *reuse_ptr, std::size_t sizeof_object)
{
if(!sizeof_object)
- return std::pair<void *, bool>((void *)0, 0);
+ return std::pair<void *, bool>(static_cast<void*>(0), 0);
if(command & try_shrink_in_place){
bool success = algo_impl_t::try_shrink
( this, reuse_ptr, limit_objects*sizeof_object
@@ -724,7 +724,7 @@
//Iterate through all blocks obtaining their size
for(; ib != ie; ++ib){
//Just clear user the memory part reserved for the user
- std::memset( detail::char_ptr_cast(&*ib) + BlockCtrlBytes
+ std::memset( reinterpret_cast<char*>(&*ib) + BlockCtrlBytes
, 0
, ib->m_size*Alignment - BlockCtrlBytes);
}
@@ -801,7 +801,7 @@
//We need a minimum size to split the previous one
if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){
block_ctrl *new_block = reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(reuse) - needs_backwards_aligned);
+ (reinterpret_cast<char*>(reuse) - needs_backwards_aligned);
//Free old previous buffer
new_block->m_size =
@@ -809,8 +809,8 @@
assert(new_block->m_size >= BlockCtrlUnits);
priv_mark_new_allocated_block(new_block);
- prev_block->m_size = (detail::char_ptr_cast(new_block) -
- detail::char_ptr_cast(prev_block))/Alignment;
+ prev_block->m_size = (reinterpret_cast<char*>(new_block) -
+ reinterpret_cast<char*>(prev_block))/Alignment;
assert(prev_block->m_size >= BlockCtrlUnits);
priv_mark_as_free_block(prev_block);
@@ -836,8 +836,8 @@
//If the backwards expansion has remaining bytes in the
//first bytes, fill them with a pattern
void *p = priv_get_user_buffer(new_block);
- void *user_ptr = detail::char_ptr_cast(p);
- assert(((char*)reuse_ptr - (char*)user_ptr) % backwards_multiple == 0);
+ void *user_ptr = reinterpret_cast<char*>(p);
+ assert((static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
algo_impl_t::assert_alignment(user_ptr);
return user_ptr;
}
@@ -860,9 +860,8 @@
//If the backwards expansion has remaining bytes in the
//first bytes, fill them with a pattern
- void *p = priv_get_user_buffer(prev_block);
- void *user_ptr = detail::char_ptr_cast(p);
- assert(((char*)reuse_ptr - (char*)user_ptr) % backwards_multiple == 0);
+ void *user_ptr = priv_get_user_buffer(prev_block);
+ assert((static_cast<char*>(reuse_ptr) - static_cast<char*>(user_ptr)) % backwards_multiple == 0);
algo_impl_t::assert_alignment(user_ptr);
return user_ptr;
}
@@ -932,7 +931,7 @@
received_size = 0;
if(limit_size > preferred_size)
- return return_type((void*)0, false);
+ return return_type(static_cast<void*>(0), false);
//Number of units to request (including block_ctrl header)
std::size_t preferred_units = priv_get_total_units(preferred_size);
@@ -971,7 +970,7 @@
(command, limit_size, preferred_size, received_size, reuse_ptr, false, backwards_multiple), true);
}
- return return_type((void*)0, false);
+ return return_type(static_cast<void*>(0), false);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
@@ -979,14 +978,16 @@
typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *
rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::priv_get_block(const void *ptr)
{
- return reinterpret_cast<block_ctrl*>(detail::char_ptr_cast(ptr) - AllocatedCtrlBytes);
+ return const_cast<block_ctrl*>
+ (reinterpret_cast<const block_ctrl*>
+ (reinterpret_cast<const char*>(ptr) - AllocatedCtrlBytes));
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline
void *rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::
priv_get_user_buffer(const typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *block)
-{ return detail::char_ptr_cast(block) + AllocatedCtrlBytes; }
+{ return const_cast<char*>(reinterpret_cast<const char*>(block) + AllocatedCtrlBytes); }
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment>
inline
@@ -1077,7 +1078,7 @@
}
//This is the remaining block
block_ctrl *rem_block = new(reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + intended_units*Alignment))block_ctrl;
+ (reinterpret_cast<char*>(block) + intended_units*Alignment))block_ctrl;
rem_block->m_size = rem_units;
algo_impl_t::assert_alignment(rem_block);
assert(rem_block->m_size >= BlockCtrlUnits);
@@ -1116,7 +1117,7 @@
{
assert(!ptr->m_prev_allocated);
return reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(ptr) - ptr->m_prev_size*Alignment);
+ (reinterpret_cast<char*>(ptr) - ptr->m_prev_size*Alignment);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline
@@ -1141,7 +1142,7 @@
{
assert(first_segment_block->m_prev_allocated);
block_ctrl *end_block = reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(first_segment_block) - first_segment_block->m_prev_size*Alignment);
+ (reinterpret_cast<char*>(first_segment_block) - first_segment_block->m_prev_size*Alignment);
(void)end_block;
assert(priv_is_allocated_block(end_block));
assert(end_block > first_segment_block);
@@ -1154,7 +1155,7 @@
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *ptr)
{
return reinterpret_cast<block_ctrl *>
- (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment);
+ (reinterpret_cast<char*>(ptr) + ptr->m_size*Alignment);
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline
@@ -1162,8 +1163,8 @@
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *block)
{
bool allocated = block->m_allocated != 0;
- block_ctrl *next_block = (block_ctrl *)
- (detail::char_ptr_cast(block) + block->m_size*Alignment);
+ block_ctrl *next_block = reinterpret_cast<block_ctrl *>
+ (reinterpret_cast<char*>(block) + block->m_size*Alignment);
bool next_block_prev_allocated = next_block->m_prev_allocated != 0;
(void)next_block_prev_allocated;
assert(allocated == next_block_prev_allocated);
@@ -1176,7 +1177,8 @@
{
//assert(!priv_is_allocated_block(block));
block->m_allocated = 1;
- ((block_ctrl *)(((char*)block) + block->m_size*Alignment))->m_prev_allocated = 1;
+ reinterpret_cast<block_ctrl *>
+ (reinterpret_cast<char*>(block)+ block->m_size*Alignment)->m_prev_allocated = 1;
}
template<class MutexFamily, class VoidPointer, std::size_t MemAlignment> inline
@@ -1184,7 +1186,8 @@
(typename rbtree_best_fit<MutexFamily, VoidPointer, MemAlignment>::block_ctrl *block)
{
block->m_allocated = 0;
- ((block_ctrl *)(((char*)block) + block->m_size*Alignment))->m_prev_allocated = 0;
+ reinterpret_cast<block_ctrl *>
+ (reinterpret_cast<char*>(block) + block->m_size*Alignment)->m_prev_allocated = 0;
//assert(!priv_is_allocated_block(ptr));
priv_next_block(block)->m_prev_size = block->m_size;
}
@@ -1209,7 +1212,7 @@
//This is the remaining block
block_ctrl *rem_block = new(reinterpret_cast<block_ctrl*>
- (detail::char_ptr_cast(block) + Alignment*nunits))block_ctrl;
+ (reinterpret_cast<char*>(block) + Alignment*nunits))block_ctrl;
algo_impl_t::assert_alignment(rem_block);
rem_block->m_size = block_old_size - nunits;
assert(rem_block->m_size >= BlockCtrlUnits);
Modified: trunk/boost/interprocess/offset_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/offset_ptr.hpp (original)
+++ trunk/boost/interprocess/offset_ptr.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -61,17 +61,17 @@
__declspec(noinline) //this workaround is needed for msvc-8.0 and msvc-9.0
#endif
void set_offset(const volatile void *ptr)
- { set_offset((const void*)ptr); }
+ { set_offset(const_cast<const void*>(ptr)); }
void set_offset(const void *ptr)
{
- const char *p = static_cast<const char*>(const_cast<const void*>(ptr));
+ const char *p = static_cast<const char*>(ptr);
//offset == 1 && ptr != 0 is not legal for this pointer
if(!ptr){
m_offset = 1;
}
else{
- m_offset = p - detail::char_ptr_cast(this);
+ m_offset = p - reinterpret_cast<const char*>(this);
BOOST_ASSERT(m_offset != 1);
}
}
@@ -80,7 +80,7 @@
__declspec(noinline) //this workaround is needed for msvc-8.0 and msvc-9.0
#endif
void* get_pointer() const
- { return (m_offset == 1) ? 0 : (detail::char_ptr_cast(this) + m_offset); }
+ { return (m_offset == 1) ? 0 : (const_cast<char*>(reinterpret_cast<const char*>(this)) + m_offset); }
void inc_offset(std::ptrdiff_t bytes)
{ m_offset += bytes; }
@@ -149,7 +149,7 @@
//!Obtains raw pointer from offset.
//!Never throws.
pointer get()const
- { return (pointer)this->get_pointer(); }
+ { return static_cast<pointer>(this->get_pointer()); }
std::ptrdiff_t get_offset()
{ return m_offset; }
@@ -425,13 +425,13 @@
static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u;
static pointer get_pointer(const pointer &n)
- { return (T*)(std::size_t(n.get()) & ~std::size_t(Mask)); }
+ { return reinterpret_cast<T*>(std::size_t(n.get()) & ~std::size_t(Mask)); }
static void set_pointer(pointer &n, pointer p)
{
std::size_t pint = std::size_t(p.get());
assert(0 == (std::size_t(pint) & Mask));
- n = (T*)(pint | (std::size_t(n.get()) & std::size_t(Mask)));
+ n = reinterpret_cast<T*>(pint | (std::size_t(n.get()) & std::size_t(Mask)));
}
static std::size_t get_bits(const pointer &n)
@@ -440,7 +440,7 @@
static void set_bits(pointer &n, std::size_t b)
{
assert(b < (std::size_t(1) << NumBits));
- n = (T*)(std::size_t(get_pointer(n).get()) | (b << 1u));
+ n = reinterpret_cast<T*>(std::size_t(get_pointer(n).get()) | (b << 1u));
}
};
Modified: trunk/boost/interprocess/segment_manager.hpp
==============================================================================
--- trunk/boost/interprocess/segment_manager.hpp (original)
+++ trunk/boost/interprocess/segment_manager.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -305,7 +305,7 @@
//Call destructors and free memory
//Build scoped ptr to avoid leaks with destructor exception
std::size_t destroyed = 0;
- table.destroy_n((void*)object, ctrl_data->m_value_bytes/table.size, destroyed);
+ table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
this->deallocate(ctrl_data);
}
/// @endcond
@@ -410,40 +410,38 @@
segment_manager(std::size_t size)
: Base(size, priv_get_reserved_bytes())
, m_header(static_cast<Base*>(get_this_pointer()))
- { (void) anonymous_instance; (void) unique_instance; }
+ {
+ (void) anonymous_instance; (void) unique_instance;
+ assert(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this)));
+ }
//!Tries to find a previous named allocation. Returns the address
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
std::pair<T*, std::size_t> find (const CharType* name)
- {
- //The name can't be null, no anonymous object can be found by name
- assert(name != 0);
- detail::placement_destroy<T> table;
- std::size_t size;
- void *ret;
-
- if(name == reinterpret_cast<const CharType*>(-1)){
- ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), true);
- }
- else{
- ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), true);
- }
- return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
- }
+ { return this->priv_find_impl<T>(name, true); }
//!Tries to find a previous unique allocation. Returns the address
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
std::pair<T*, std::size_t> find (const detail::unique_instance_t* name)
- {
- detail::placement_destroy<T> table;
- std::size_t size;
- void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), true);
- return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
- }
+ { return this->priv_find_impl<T>(name, true); }
+
+ //!Tries to find a previous named allocation. Returns the address
+ //!and the object count. On failure the first member of the
+ //!returned pair is 0. This search is not mutex-protected!
+ template <class T>
+ std::pair<T*, std::size_t> find_no_lock (const CharType* name)
+ { return this->priv_find_impl<T>(name, false); }
+
+ //!Tries to find a previous unique allocation. Returns the address
+ //!and the object count. On failure the first member of the
+ //!returned pair is 0. This search is not mutex-protected!
+ template <class T>
+ std::pair<T*, std::size_t> find_no_lock (const detail::unique_instance_t* name)
+ { return this->priv_find_impl<T>(name, false); }
//!Returns throwing "construct" proxy
//!object
@@ -690,11 +688,12 @@
(priv_generic_construct(name, num, try2find, dothrow, table));
}
+ private:
//!Tries to find a previous named allocation. Returns the address
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
- std::pair<T*, std::size_t> find_no_lock (const CharType* name)
+ std::pair<T*, std::size_t> priv_find_impl (const CharType* name, bool lock)
{
//The name can't be null, no anonymous object can be found by name
assert(name != 0);
@@ -703,10 +702,10 @@
void *ret;
if(name == reinterpret_cast<const CharType*>(-1)){
- ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), false);
+ ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), lock);
}
else{
- ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), false);
+ ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), lock);
}
return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
}
@@ -715,15 +714,14 @@
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
- std::pair<T*, std::size_t> find_no_lock (const detail::unique_instance_t* name)
+ std::pair<T*, std::size_t> priv_find__impl (const detail::unique_instance_t* name, bool lock)
{
detail::placement_destroy<T> table;
std::size_t size;
- void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), false);
+ void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock);
return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
}
- private:
void *priv_generic_construct(const CharType *name,
std::size_t num,
bool try2find,
@@ -815,8 +813,7 @@
{
//Get the number of bytes until the end of (*this)
//beginning in the end of the Base base.
- return (detail::char_ptr_cast((segment_manager*)0) + sizeof(segment_manager)) -
- (detail::char_ptr_cast(static_cast<Base*>((segment_manager*)0)) + sizeof(Base));
+ return sizeof(segment_manager) - sizeof(Base);
}
template <class CharT>
@@ -1014,7 +1011,7 @@
//Get allocation parameters
block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
(detail::get_pointer(it->second.m_ptr));
- char *stored_name = detail::char_ptr_cast(it->first.name());
+ char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
(void)stored_name;
//Check if the distance between the name pointer and the memory pointer
@@ -1024,7 +1021,7 @@
//Sanity check
assert((ctrl_data->m_value_bytes % table.size) == 0);
- assert((void*)stored_name == ctrl_data->template name<CharT>());
+ assert(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
assert(sizeof(CharT) == ctrl_data->sizeof_char());
//Erase node from index
@@ -1113,7 +1110,12 @@
if(try2find){
return it->get_block_header()->value();
}
- return 0;
+ if(dothrow){
+ throw interprocess_exception(already_exists_error);
+ }
+ else{
+ return 0;
+ }
}
//Allocates buffer for name + data, this can throw (it hurts)
@@ -1153,22 +1155,23 @@
}
BOOST_CATCH_END
- //Initialize the node value_eraser to erase inserted node
- //if something goes wrong
- value_eraser<index_type> v_eraser(index, it);
-
//Avoid constructions if constructor is trivial
//Build scoped ptr to avoid leaks with constructor exception
detail::mem_algo_deallocator<segment_manager_base_type> mem
(buffer_ptr, *static_cast<segment_manager_base_type*>(this));
+ //Initialize the node value_eraser to erase inserted node
+ //if something goes wrong. This will be executed *before*
+ //the memory allocation as the intrusive value is built in that
+ //memory
+ value_eraser<index_type> v_eraser(index, it);
+
//Construct array, this can throw
detail::array_construct(ptr, num, table);
- //All constructors successful, we don't want to release memory
- mem.release();
- //Release node v_eraser since construction was successful
+ //Release rollbacks since construction was successful
v_eraser.release();
+ mem.release();
return ptr;
}
@@ -1216,8 +1219,7 @@
//the key (which is a smart pointer) to an equivalent one
index_ib insert_ret;
BOOST_TRY{
- insert_ret = index.insert(value_type(key_type (name, namelen),
- mapped_type(0)));
+ insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
}
//Ignore exceptions
BOOST_CATCH(...){
Modified: trunk/boost/interprocess/shared_memory_object.hpp
==============================================================================
--- trunk/boost/interprocess/shared_memory_object.hpp (original)
+++ trunk/boost/interprocess/shared_memory_object.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -220,6 +220,7 @@
throw interprocess_exception(err);
}
+ //detail::delete_file_on_reboot_if_possible(shmfile.c_str());
m_mode = mode;
return true;
}
Modified: trunk/boost/interprocess/smart_ptr/unique_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/smart_ptr/unique_ptr.hpp (original)
+++ trunk/boost/interprocess/smart_ptr/unique_ptr.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -593,7 +593,7 @@
> type;
};
-//!Returns an instance of the a unique pointer constructed
+//!Returns an instance of a unique pointer constructed
//!with boost::interproces::deleter from a pointer
//!of type T that has been allocated in the passed managed segment
template<class T, class ManagedMemory>
Modified: trunk/boost/interprocess/smart_ptr/weak_ptr.hpp
==============================================================================
--- trunk/boost/interprocess/smart_ptr/weak_ptr.hpp (original)
+++ trunk/boost/interprocess/smart_ptr/weak_ptr.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -236,7 +236,7 @@
> type;
};
-//!Returns an instance of the a weak pointer constructed
+//!Returns an instance of a weak pointer constructed
//!with the default allocator and deleter from a pointer
//!of type T that has been allocated in the passed managed segment
template<class T, class ManagedMemory>
Modified: trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp (original)
+++ trunk/boost/interprocess/sync/emulation/interprocess_condition.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -53,12 +53,12 @@
}
//Notify that all threads should execute wait logic
- while(SLEEP != detail::atomic_cas32((boost::uint32_t*)&m_command, command, SLEEP)){
+ while(SLEEP != detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
detail::thread_yield();
}
/*
//Wait until the threads are woken
- while(SLEEP != detail::atomic_cas32((boost::uint32_t*)&m_command, 0)){
+ while(SLEEP != detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_command), 0)){
detail::thread_yield();
}
*/
@@ -107,7 +107,7 @@
//We increment the waiting thread count protected so that it will be
//always constant when another thread enters the notification logic.
//The increment marks this thread as "waiting on interprocess_condition"
- detail::atomic_inc32((boost::uint32_t*)&m_num_waiters);
+ detail::atomic_inc32(const_cast<boost::uint32_t*>(&m_num_waiters));
//We unlock the external interprocess_mutex atomically with the increment
mut.unlock();
@@ -150,7 +150,7 @@
//If a timeout occurred, the interprocess_mutex will not execute checking logic
if(tout_enabled && timed_out){
//Decrement wait count
- detail::atomic_dec32((boost::uint32_t*)&m_num_waiters);
+ detail::atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
unlock_enter_mut = true;
break;
}
@@ -172,7 +172,7 @@
return false;
//---------------------------------------------------------------
boost::uint32_t result = detail::atomic_cas32
- ((boost::uint32_t*)&m_command, SLEEP, NOTIFY_ONE);
+ (const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ONE);
if(result == SLEEP){
//Other thread has been notified and since it was a NOTIFY one
//command, this thread must sleep again
@@ -184,17 +184,17 @@
//so no other thread will exit.
//Decrement wait count.
unlock_enter_mut = true;
- detail::atomic_dec32((boost::uint32_t*)&m_num_waiters);
+ detail::atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
break;
}
else{
//If it is a NOTIFY_ALL command, all threads should return
//from do_timed_wait function. Decrement wait count.
- unlock_enter_mut = 1 == detail::atomic_dec32((boost::uint32_t*)&m_num_waiters);
+ unlock_enter_mut = 1 == detail::atomic_dec32(const_cast<boost::uint32_t*>(&m_num_waiters));
//Check if this is the last thread of notify_all waiters
//Only the last thread will release the interprocess_mutex
if(unlock_enter_mut){
- detail::atomic_cas32((boost::uint32_t*)&m_command, SLEEP, NOTIFY_ALL);
+ detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_command), SLEEP, NOTIFY_ALL);
}
break;
}
Modified: trunk/boost/interprocess/sync/emulation/interprocess_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/emulation/interprocess_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/emulation/interprocess_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -30,7 +30,7 @@
inline void interprocess_mutex::lock(void)
{
do{
- boost::uint32_t prev_s = detail::atomic_cas32((boost::uint32_t*)&m_s, 1, 0);
+ boost::uint32_t prev_s = detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
if (m_s == 1 && prev_s == 0){
break;
@@ -42,12 +42,16 @@
inline bool interprocess_mutex::try_lock(void)
{
- boost::uint32_t prev_s = detail::atomic_cas32((boost::uint32_t*)&m_s, 1, 0);
+ boost::uint32_t prev_s = detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
return m_s == 1 && prev_s == 0;
}
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
//Obtain current count and target time
boost::posix_time::ptime now = microsec_clock::universal_time();
@@ -70,7 +74,7 @@
}
inline void interprocess_mutex::unlock(void)
-{ detail::atomic_cas32((boost::uint32_t*)&m_s, 0, 1); }
+{ detail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 0, 1); }
} //namespace interprocess {
Modified: trunk/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -75,6 +75,10 @@
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
detail::OS_thread_id_t th_id = detail::get_current_thread_id();
if(detail::equal_thread_id(th_id, m_nOwner)) { // we own it
if((unsigned int)(m_nLockCount+1) == 0){
Modified: trunk/boost/interprocess/sync/emulation/interprocess_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/emulation/interprocess_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/emulation/interprocess_semaphore.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -52,6 +52,10 @@
inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
scoped_lock<interprocess_mutex> lock(m_mut);
while(m_count == 0){
if(!m_cond.timed_wait(lock, abs_time))
Modified: trunk/boost/interprocess/sync/file_lock.hpp
==============================================================================
--- trunk/boost/interprocess/sync/file_lock.hpp (original)
+++ trunk/boost/interprocess/sync/file_lock.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -205,6 +205,10 @@
inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
bool result;
if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){
error_info err(system_error_code());
@@ -241,6 +245,10 @@
inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
bool result;
if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
error_info err(system_error_code());
Modified: trunk/boost/interprocess/sync/interprocess_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_condition.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_condition.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -26,7 +26,7 @@
#include <boost/limits.hpp>
#include <cassert>
-#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
@@ -107,9 +107,12 @@
template <typename L>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
if (!lock)
throw lock_exception();
-
return do_timed_wait(abs_time, *lock.mutex());
}
@@ -119,9 +122,12 @@
template <typename L, typename Pr>
bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
if (!lock)
throw lock_exception();
-
while (!pred()){
if (!do_timed_wait(abs_time, *lock.mutex()))
return pred();
Modified: trunk/boost/interprocess/sync/interprocess_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -36,7 +36,7 @@
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <cassert>
-#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
Modified: trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_recursive_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -36,7 +36,8 @@
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#include <cassert>
-#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED && defined BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
+ (defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES))
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
Modified: trunk/boost/interprocess/sync/interprocess_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_semaphore.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -21,8 +21,8 @@
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
-#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED &&\
- defined BOOST_INTERPROCESS_POSIX_SEMAPHORES
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
+ (defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES))
#include <fcntl.h> //O_CREAT, O_*...
#include <unistd.h> //close
#include <string> //std::string
Modified: trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/interprocess_upgradable_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -322,6 +322,10 @@
inline bool interprocess_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
scoped_lock_t lock(m_mut, abs_time);
if(!lock.owns()) return false;
@@ -399,6 +403,10 @@
inline bool interprocess_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_upgradable();
+ return true;
+ }
scoped_lock_t lock(m_mut, abs_time);
if(!lock.owns()) return false;
@@ -471,6 +479,10 @@
inline bool interprocess_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
scoped_lock_t lock(m_mut, abs_time);
if(!lock.owns()) return false;
Modified: trunk/boost/interprocess/sync/lock_options.hpp
==============================================================================
--- trunk/boost/interprocess/sync/lock_options.hpp (original)
+++ trunk/boost/interprocess/sync/lock_options.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -41,7 +41,7 @@
//!must be deferred.
static const detail::defer_lock_type defer_lock = detail::defer_lock_type();
-//!An object indicating that the a try_lock()
+//!An object indicating that a try_lock()
//!operation must be executed.
static const detail::try_to_lock_type try_to_lock = detail::try_to_lock_type();
Modified: trunk/boost/interprocess/sync/named_condition.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_condition.hpp (original)
+++ trunk/boost/interprocess/sync/named_condition.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -259,6 +259,10 @@
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
if (!lock)
throw lock_exception();
return this->do_timed_wait(lock, abs_time);
@@ -268,6 +272,10 @@
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
if (!lock)
throw lock_exception();
@@ -309,6 +317,10 @@
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock);
+ return true;
+ }
if (!lock)
throw lock_exception();
return this->condition()->do_timed_wait(abs_time, *lock.mutex()->mutex());
@@ -318,6 +330,10 @@
inline bool named_condition::timed_wait
(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait(lock, pred);
+ return true;
+ }
if (!lock)
throw lock_exception();
Modified: trunk/boost/interprocess/sync/named_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -150,7 +150,13 @@
{ return m_sem.try_wait(); }
inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{ return m_sem.timed_wait(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return m_sem.timed_wait(abs_time);
+}
inline bool named_mutex::remove(const char *name)
{ return detail::named_semaphore_wrapper::remove(name); }
@@ -203,7 +209,13 @@
{ return this->mutex()->try_lock(); }
inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{ return this->mutex()->timed_lock(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
inline bool named_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
Modified: trunk/boost/interprocess/sync/named_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_recursive_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -156,7 +156,13 @@
{ return this->mutex()->try_lock(); }
inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
-{ return this->mutex()->timed_lock(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
inline bool named_recursive_mutex::remove(const char *name)
{ return shared_memory_object::remove(name); }
Modified: trunk/boost/interprocess/sync/named_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/named_semaphore.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -154,7 +154,13 @@
{ return m_sem.try_wait(); }
inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
-{ return m_sem.timed_wait(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ return m_sem.timed_wait(abs_time);
+}
inline bool named_semaphore::remove(const char *name)
{ return detail::named_semaphore_wrapper::remove(name); }
@@ -210,7 +216,13 @@
{ return semaphore()->try_wait(); }
inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
-{ return semaphore()->timed_wait(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ return semaphore()->timed_wait(abs_time);
+}
inline bool named_semaphore::remove(const char *name)
{ return shared_memory_object::remove(name); }
Modified: trunk/boost/interprocess/sync/named_upgradable_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/named_upgradable_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/named_upgradable_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -185,7 +185,7 @@
//!Precondition: The thread must have upgradable ownership of the mutex.
//!Effects: The thread atomically releases upgradable ownership and acquires
//! exclusive ownership. This operation will block until all threads with
- //! sharable ownership releas it.
+ //! sharable ownership release it.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_upgradable_and_lock();
@@ -285,7 +285,13 @@
inline bool named_upgradable_mutex::timed_lock
(const boost::posix_time::ptime &abs_time)
-{ return this->mutex()->timed_lock(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ return this->mutex()->timed_lock(abs_time);
+}
inline void named_upgradable_mutex::lock_upgradable()
{ this->mutex()->lock_upgradable(); }
@@ -298,7 +304,13 @@
inline bool named_upgradable_mutex::timed_lock_upgradable
(const boost::posix_time::ptime &abs_time)
-{ return this->mutex()->timed_lock_upgradable(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_upgradable();
+ return true;
+ }
+ return this->mutex()->timed_lock_upgradable(abs_time);
+}
inline void named_upgradable_mutex::lock_sharable()
{ this->mutex()->lock_sharable(); }
@@ -311,7 +323,13 @@
inline bool named_upgradable_mutex::timed_lock_sharable
(const boost::posix_time::ptime &abs_time)
-{ return this->mutex()->timed_lock_sharable(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock_sharable();
+ return true;
+ }
+ return this->mutex()->timed_lock_sharable(abs_time);
+}
inline void named_upgradable_mutex::unlock_and_lock_upgradable()
{ this->mutex()->unlock_and_lock_upgradable(); }
Modified: trunk/boost/interprocess/sync/posix/interprocess_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/interprocess_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/posix/interprocess_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -63,6 +63,10 @@
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
timespec ts = detail::ptime_to_timespec(abs_time);
Modified: trunk/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp (original)
+++ trunk/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -64,6 +64,10 @@
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
timespec ts = detail::ptime_to_timespec(abs_time);
Modified: trunk/boost/interprocess/sync/posix/interprocess_semaphore.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/interprocess_semaphore.hpp (original)
+++ trunk/boost/interprocess/sync/posix/interprocess_semaphore.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -32,7 +32,13 @@
{ return m_sem.try_wait(); }
inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
-{ return m_sem.timed_wait(abs_time); }
+{
+ if(abs_time == boost::posix_time::pos_infin){
+ this->wait();
+ return true;
+ }
+ return m_sem.timed_wait(abs_time);
+}
/*
inline int interprocess_semaphore::get_count() const
{ return m_sem.get_count(); }
Modified: trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp
==============================================================================
--- trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp (original)
+++ trunk/boost/interprocess/sync/posix/semaphore_wrapper.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -22,7 +22,7 @@
#ifdef SEM_FAILED
#define BOOST_INTERPROCESS_POSIX_SEM_FAILED SEM_FAILED
#else
-#define BOOST_INTERPROCESS_POSIX_SEM_FAILED ((sem_t*)(-1))
+#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
#endif
#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
Modified: trunk/boost/interprocess/sync/sharable_lock.hpp
==============================================================================
--- trunk/boost/interprocess/sync/sharable_lock.hpp (original)
+++ trunk/boost/interprocess/sync/sharable_lock.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -48,7 +48,7 @@
//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among
//!sharable_locks, and a single upgradable_lock. sharable_lock does not support
//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock,
-//!upgradable_lock and scoped_lock via trasfer_lock syntax.*/
+//!upgradable_lock and scoped_lock via transfer_lock syntax.*/
template <class SharableMutex>
class sharable_lock
{
Modified: trunk/boost/interprocess/sync/upgradable_lock.hpp
==============================================================================
--- trunk/boost/interprocess/sync/upgradable_lock.hpp (original)
+++ trunk/boost/interprocess/sync/upgradable_lock.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -43,12 +43,12 @@
//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking,
//!try-read-locking and timed-read-locking (recursive or not) for the Mutex.
//!Additionally the upgradable_lock can transfer ownership to a scoped_lock
-//!using trasfer_lock syntax. The Mutex need not supply all of the functionality.
+//!using transfer_lock syntax. The Mutex need not supply all of the functionality.
//!If the client of upgradable_lock<Mutex> does not use functionality which the
//!Mutex does not supply, no harm is done. Mutex ownership can be shared among
//!read_locks, and a single upgradable_lock. upgradable_lock does not support
//!copy semantics. However upgradable_lock supports ownership transfer from
-//!a upgradable_locks or scoped_locks via trasfer_lock syntax.
+//!a upgradable_locks or scoped_locks via transfer_lock syntax.
template <class UpgradableMutex>
class upgradable_lock
{
Modified: trunk/boost/intrusive/any_hook.hpp
==============================================================================
--- trunk/boost/intrusive/any_hook.hpp (original)
+++ trunk/boost/intrusive/any_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -34,7 +34,7 @@
//! Helper metafunction to define a \c \c any_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -43,8 +43,14 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
-
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+
typedef detail::generic_hook
< get_any_node_algo<typename packed_options::void_pointer>
, typename packed_options::tag
@@ -70,15 +76,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class any_base_hook
- : public make_any_base_hook<O1, O2, O3>::type
+ : public make_any_base_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
@@ -127,7 +139,7 @@
//! Helper metafunction to define a \c \c any_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -136,7 +148,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_any_node_algo<typename packed_options::void_pointer>
@@ -158,15 +176,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class any_member_hook
- : public make_any_member_hook<O1, O2, O3>::type
+ : public make_any_member_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
public:
//! <b>Effects</b>: If link_mode is or \c safe_link
//! initializes the node to an unlinked state.
Modified: trunk/boost/intrusive/avl_set.hpp
==============================================================================
--- trunk/boost/intrusive/avl_set.hpp (original)
+++ trunk/boost/intrusive/avl_set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -31,7 +31,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -323,18 +323,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -996,65 +997,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y)
#else
(const avl_set_impl<Config> &x, const avl_set_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y)
#else
(const avl_set_impl<Config> &x, const avl_set_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y)
#else
(const avl_set_impl<Config> &x, const avl_set_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_set_impl<T, Options...> &x, const avl_set_impl<T, Options...> &y)
#else
(const avl_set_impl<Config> &x, const avl_set_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(avl_set_impl<T, Options...> &x, avl_set_impl<T, Options...> &y)
#else
(avl_set_impl<Config> &x, avl_set_impl<Config> &y)
@@ -1063,7 +1064,7 @@
//! Helper metafunction to define a \c avl_set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1073,19 +1074,41 @@
{
/// @cond
typedef avl_set_impl
- < typename make_avltree_opt<T, O1, O2, O3, O4>::type
+ < typename make_avltree_opt
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class avl_set
- : public make_avl_set<T, O1, O2, O3, O4>::type
+ : public make_avl_set
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type
{
typedef typename make_avl_set
- <T, O1, O2, O3, O4>::type Base;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type Base;
public:
typedef typename Base::value_compare value_compare;
@@ -1134,7 +1157,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1422,18 +1445,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -2002,65 +2026,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y)
#else
(const avl_multiset_impl<Config> &x, const avl_multiset_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y)
#else
(const avl_multiset_impl<Config> &x, const avl_multiset_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y)
#else
(const avl_multiset_impl<Config> &x, const avl_multiset_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avl_multiset_impl<T, Options...> &x, const avl_multiset_impl<T, Options...> &y)
#else
(const avl_multiset_impl<Config> &x, const avl_multiset_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(avl_multiset_impl<T, Options...> &x, avl_multiset_impl<T, Options...> &y)
#else
(avl_multiset_impl<Config> &x, avl_multiset_impl<Config> &y)
@@ -2069,7 +2093,7 @@
//! Helper metafunction to define a \c avl_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -2079,19 +2103,41 @@
{
/// @cond
typedef avl_multiset_impl
- < typename make_avltree_opt<T, O1, O2, O3, O4>::type
+ < typename make_avltree_opt
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class avl_multiset
- : public make_avl_multiset<T, O1, O2, O3, O4>::type
+ : public make_avl_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_avl_multiset
- <T, O1, O2, O3, O4>::type Base;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/avl_set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/avl_set_hook.hpp (original)
+++ trunk/boost/intrusive/avl_set_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -34,7 +34,7 @@
//! Helper metafunction to define a \c avl_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -43,7 +43,12 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <hook_defaults, O1, O2, O3, O4>
+ #else
+ <hook_defaults, Options...>
+ #endif
+ ::type packed_options;
typedef detail::generic_hook
< get_avl_set_node_algo<typename packed_options::void_pointer
@@ -76,15 +81,21 @@
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class avl_set_base_hook
- : public make_avl_set_base_hook<O1, O2, O3, O4>::type
+ : public make_avl_set_base_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3, O4>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -153,7 +164,7 @@
//! Helper metafunction to define a \c avl_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -162,7 +173,12 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <hook_defaults, O1, O2, O3, O4>
+ #else
+ <hook_defaults, Options...>
+ #endif
+ ::type packed_options;
typedef detail::generic_hook
< get_avl_set_node_algo<typename packed_options::void_pointer
@@ -190,15 +206,21 @@
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class avl_set_member_hook
- : public make_avl_set_member_hook<O1, O2, O3, O4>::type
+ : public make_avl_set_member_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3, O4>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Modified: trunk/boost/intrusive/avltree.hpp
==============================================================================
--- trunk/boost/intrusive/avltree.hpp (original)
+++ trunk/boost/intrusive/avltree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -36,20 +36,6 @@
/// @cond
-template <class T>
-struct internal_default_avl_set_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_avl_set_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_avl_set_hook
-{
- typedef typename T::default_avl_set_hook type;
-};
-
template <class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize>
struct avl_setopt
{
@@ -63,13 +49,7 @@
struct avl_set_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_avl_set_hook<T>::value
- , get_default_avl_set_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_avl_set_hook>
, constant_time_size<true>
, size_type<std::size_t>
, compare<std::less<T> >
@@ -91,7 +71,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1055,29 +1035,34 @@
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer)
{
this->clear_and_dispose(disposer);
if(!src.empty()){
+ detail::exception_disposer<avltree_impl, Disposer>
+ rollback(*this, disposer);
node_algorithms::clone
(const_node_ptr(&src.priv_header())
,node_ptr(&this->priv_header())
,detail::node_cloner<Cloner, avltree_impl>(cloner, this)
,detail::node_disposer<Disposer, avltree_impl>(disposer, this));
this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ this->priv_comp() = src.priv_comp();
+ rollback.release();
}
}
@@ -1260,26 +1245,26 @@
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
@@ -1311,65 +1296,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const avltree_impl<T, Options...> &x, const avltree_impl<T, Options...> &y)
#else
(const avltree_impl<Config> &x, const avltree_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(avltree_impl<T, Options...> &x, avltree_impl<T, Options...> &y)
#else
(avltree_impl<Config> &x, avltree_impl<Config> &y)
@@ -1377,15 +1362,24 @@
{ x.swap(y); }
/// @cond
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
- , class O5 = none, class O6 = none
- , class O7 = none
>
+#else
+template<class T, class ...Options>
+#endif
struct make_avltree_opt
{
typedef typename pack_options
- < avl_set_defaults<T>, O1, O2, O3, O4>::type packed_options;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ < avl_set_defaults<T>, O1, O2, O3, O4>
+ #else
+ < avl_set_defaults<T>, Options...>
+ #endif
+ ::type packed_options;
+
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
@@ -1400,7 +1394,7 @@
//! Helper metafunction to define a \c avltree that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1410,19 +1404,37 @@
{
/// @cond
typedef avltree_impl
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
< typename make_avltree_opt<T, O1, O2, O3, O4>::type
+ #else
+ < typename make_avltree_opt<T, Options...>::type
+ #endif
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class avltree
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
: public make_avltree<T, O1, O2, O3, O4>::type
+ #else
+ : public make_avltree<T, Options...>::type
+ #endif
{
typedef typename make_avltree
- <T, O1, O2, O3, O4>::type Base;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <T, O1, O2, O3, O4>
+ #else
+ <T, Options...>
+ #endif
+ ::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/avltree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/avltree_algorithms.hpp (original)
+++ trunk/boost/intrusive/avltree_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -682,10 +682,10 @@
// x is right child
// a is left child
node_ptr a = NodeTraits::get_left(x_parent);
- assert(a);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
if (NodeTraits::get_balance(a) == NodeTraits::positive()) {
// a MUST have a right child
- assert(NodeTraits::get_right(a));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a));
rotate_left_right(x_parent, root);
x = NodeTraits::get_parent(x_parent);
@@ -714,10 +714,10 @@
// x is left child
// a is right child
node_ptr a = NodeTraits::get_right(x_parent);
- assert(a);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(a);
if (NodeTraits::get_balance(a) == NodeTraits::negative()) {
// a MUST have then a left child
- assert(NodeTraits::get_left(a));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a));
rotate_right_left(x_parent, root);
x = NodeTraits::get_parent(x_parent);
@@ -735,7 +735,7 @@
}
}
else{
- assert(false); // never reached
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
}
NodeTraits::set_parent(header, root);
@@ -784,7 +784,7 @@
break;
}
else{
- assert(false); // never reached
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
}
NodeTraits::set_parent(header, root);
@@ -842,7 +842,7 @@
NodeTraits::set_balance(b, NodeTraits::negative());
}
else{
- assert(false); // never reached
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached
}
NodeTraits::set_balance(c, NodeTraits::zero());
}
@@ -899,7 +899,7 @@
NodeTraits::set_balance(b, NodeTraits::zero());
}
else{
- assert(false);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(false);
}
NodeTraits::set_balance(c, NodeTraits::zero());
}
Modified: trunk/boost/intrusive/bs_set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/bs_set_hook.hpp (original)
+++ trunk/boost/intrusive/bs_set_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -34,7 +34,7 @@
//! Helper metafunction to define a \c bs_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -43,7 +43,12 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ < hook_defaults, O1, O2, O3>
+ #else
+ < hook_defaults, Options...>
+ #endif
+ ::type packed_options;
//Scapegoat trees can't be auto unlink trees
BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink));
@@ -75,15 +80,22 @@
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class bs_set_base_hook
- : public make_bs_set_base_hook<O1, O2, O3>::type
+ : public make_bs_set_base_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
+
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -152,7 +164,7 @@
//! Helper metafunction to define a \c bs_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -161,7 +173,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ < hook_defaults, O1, O2, O3>
+ #else
+ < hook_defaults, Options...>
+ #endif
+
+ ::type packed_options;
//Scapegoat trees can't be auto unlink trees
BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink));
@@ -187,15 +205,21 @@
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class bs_set_member_hook
- : public make_bs_set_member_hook<O1, O2, O3>::type
+ : public make_bs_set_member_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -262,24 +286,6 @@
#endif
};
-/// @cond
-
-template <class T>
-struct internal_default_bs_set_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_bs_set_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_bs_set_hook
-{
- typedef typename T::default_bs_set_hook type;
-};
-
-/// @endcond
-
} //namespace intrusive
} //namespace boost
Modified: trunk/boost/intrusive/circular_slist_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/circular_slist_algorithms.hpp (original)
+++ trunk/boost/intrusive/circular_slist_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -59,7 +59,7 @@
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
@@ -128,7 +128,7 @@
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
- #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
Modified: trunk/boost/intrusive/detail/assert.hpp
==============================================================================
--- trunk/boost/intrusive/detail/assert.hpp (original)
+++ trunk/boost/intrusive/detail/assert.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -18,18 +18,24 @@
#endif
#if !defined(BOOST_INTRUSIVE_INVARIANT_ASSERT)
-#include <boost/assert.hpp>
-#define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT
+ #include <boost/assert.hpp>
+ #define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT
+#elif defined(BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE)
+ #include BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE
#endif
#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT)
-#include <boost/assert.hpp>
-#define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT
+ #include <boost/assert.hpp>
+ #define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT
+#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE)
+ #include BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE
#endif
#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT)
-#include <boost/assert.hpp>
-#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT
+ #include <boost/assert.hpp>
+ #define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT
+#elif defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE)
+ #include BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE
#endif
#endif //BOOST_INTRUSIVE_DETAIL_ASSERT_HPP
Modified: trunk/boost/intrusive/detail/list_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/list_node.hpp (original)
+++ trunk/boost/intrusive/detail/list_node.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -161,6 +161,9 @@
return 0;
}
+ list_iterator<Container, false> unconst() const
+ { return list_iterator<Container, false>(this->pointed_node(), this->get_container()); }
+
private:
struct members
: public detail::select_constptr
Modified: trunk/boost/intrusive/detail/mpl.hpp
==============================================================================
--- trunk/boost/intrusive/detail/mpl.hpp (original)
+++ trunk/boost/intrusive/detail/mpl.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -51,6 +51,12 @@
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T>{};
+template<class F, class Param>
+struct apply
+{
+ typedef typename F::template apply<Param>::type type;
+};
+
template <class T, class U>
class is_convertible
{
@@ -127,83 +133,127 @@
#define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
#endif
-no_type BOOST_INTRUSIVE_TT_DECL is_function_ptr_tester(...);
-
-template <class R >
-yes_type is_function_ptr_tester(R (*)());
-
-template <class R >
-yes_type is_function_ptr_tester(R (*)( ...));
+template <typename T>
+struct is_unary_or_binary_function_impl
+{ static const bool value = false; };
+template <typename R>
+struct is_unary_or_binary_function_impl<R (*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (*)(...)>
+{ static const bool value = true; };
+/*
#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
-template <class R >
-yes_type is_function_ptr_tester(R (__stdcall*)());
-template <class R >
-yes_type is_function_ptr_tester(R (__stdcall*)( ...));
-
-template <class R >
-yes_type is_function_ptr_tester(R (__fastcall*)());
-template <class R >
-yes_type is_function_ptr_tester(R (__fastcall*)( ...));
-
-template <class R >
-yes_type is_function_ptr_tester(R (__cdecl*)());
-template <class R >
-yes_type is_function_ptr_tester(R (__cdecl*)( ...));
-#endif
-
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (*)( T0));
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (*)( T0 ...));
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__stdcall*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(...)>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(...)>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__fastcall*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__fastcall*)(...)>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__cdecl*)()>
+{ static const bool value = true; };
+
+template <typename R>
+struct is_unary_or_binary_function_impl<R (__cdecl*)(...)>
+{ static const bool value = true; };
+#endif
+*/
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (*)(T0)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (*)(T0...)>
+{ static const bool value = true; };
#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (__stdcall*)( T0));
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (__stdcall*)( T0 ...));
-
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (__fastcall*)( T0));
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (__fastcall*)( T0 ...));
-template <class R , class T0 >
-yes_type is_function_ptr_tester(R (__cdecl*)( T0));
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(T0)>
+{ static const bool value = true; };
+/*
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(T0...)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__fastcall*)(T0)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__fastcall*)(T0...)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__cdecl*)(T0)>
+{ static const bool value = true; };
+
+template <typename R, class T0>
+struct is_unary_or_binary_function_impl<R (__cdecl*)(T0...)>
+{ static const bool value = true; };
+*/
#endif
-template <class R , class T0 , class T1 >
-yes_type is_function_ptr_tester(R (*)( T0 , T1));
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (*)(T0, T1)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (*)(T0, T1...)>
+{ static const bool value = true; };
+/*
#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS
-template <class R , class T0 , class T1 >
-yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1));
-
-template <class R , class T0 , class T1 >
-yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1));
-template <class R , class T0 , class T1 >
-yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1));
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(T0, T1)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__stdcall*)(T0, T1...)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__fastcall*)(T0, T1)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__fastcall*)(T0, T1...)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__cdecl*)(T0, T1)>
+{ static const bool value = true; };
+
+template <typename R, class T0, class T1>
+struct is_unary_or_binary_function_impl<R (__cdecl*)(T0, T1...)>
+{ static const bool value = true; };
#endif
-
-template <typename T>
-struct is_unary_or_binary_function_impl
-{
- static T* t;
- static const bool value = sizeof(is_function_ptr_tester(t)) == sizeof(yes_type);
-};
-
+*/
template <typename T>
struct is_unary_or_binary_function_impl<T&>
-{
- static const bool value = false;
-};
+{ static const bool value = false; };
template<typename T>
struct is_unary_or_binary_function
-{
- static const bool value = is_unary_or_binary_function_impl<T>::value;
-};
+{ static const bool value = is_unary_or_binary_function_impl<T>::value; };
//boost::alignment_of yields to 10K lines of preprocessed code, so we
//need an alternative
Modified: trunk/boost/intrusive/detail/slist_node.hpp
==============================================================================
--- trunk/boost/intrusive/detail/slist_node.hpp (original)
+++ trunk/boost/intrusive/detail/slist_node.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -128,6 +128,9 @@
return 0;
}
+ slist_iterator<Container, false> unconst() const
+ { return slist_iterator<Container, false>(this->pointed_node(), this->get_container()); }
+
const real_value_traits *get_real_value_traits() const
{
if(store_container_ptr)
Modified: trunk/boost/intrusive/detail/tree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/detail/tree_algorithms.hpp (original)
+++ trunk/boost/intrusive/detail/tree_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -1391,14 +1391,14 @@
//Taken from:
//"Tree rebalancing in optimal time and space"
//Quentin F. Stout and Bette L. Warren
- std::size_t len;
+ std::size_t len = 0;
subtree_to_vine(NodeTraits::get_parent(header), &len);
vine_to_subtree(NodeTraits::get_parent(header), len);
}
static node_ptr rebalance_subtree(node_ptr old_root)
{
- std::size_t len;
+ std::size_t len = 0;
node_ptr new_root = subtree_to_vine(old_root, &len);
return vine_to_subtree(new_root, len);
}
Added: trunk/boost/intrusive/detail/workaround.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/intrusive/detail/workaround.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -0,0 +1,30 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2008. 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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_INTRUSIVE_DETAIL_WRKRND_HPP
+#define BOOST_INTRUSIVE_DETAIL_WRKRND_HPP
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)
+// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
+// passed on the command line, which in turn defines
+// __GXX_EXPERIMENTAL_CXX0X__. Note: __GXX_EXPERIMENTAL_CPP0X__ is
+// defined by some very early development versions of GCC 4.3; we will
+// remove this part of the check in the near future.
+# if defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_INTRUSIVE_RVALUE_REFERENCE
+# define BOOST_INTRUSIVE_VARIADIC_TEMPLATES
+# endif
+#endif
+
+#if defined(BOOST_INTRUSIVE_RVALUE_REFERENCE) && defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+#define BOOST_INTRUSIVE_PERFECT_FORWARDING
+#endif
+
+#endif //#ifndef BOOST_INTRUSIVE_DETAIL_WRKRND_HPP
Modified: trunk/boost/intrusive/hashtable.hpp
==============================================================================
--- trunk/boost/intrusive/hashtable.hpp (original)
+++ trunk/boost/intrusive/hashtable.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -43,6 +43,50 @@
namespace detail {
+struct hash_bool_flags
+{
+ static const std::size_t unique_keys_pos = 1u;
+ static const std::size_t constant_time_size_pos = 2u;
+ static const std::size_t power_2_buckets_pos = 4u;
+ static const std::size_t cache_begin_pos = 8u;
+ static const std::size_t compare_hash_pos = 16u;
+ static const std::size_t incremental_pos = 32u;
+};
+
+template
+ < class ValueTraits
+ , class Hash
+ , class Equal
+ , class SizeType
+ , class BucketTraits
+ , std::size_t BoolFlags
+ >
+struct usetopt
+{
+ typedef ValueTraits value_traits;
+ typedef Hash hash;
+ typedef Equal equal;
+ typedef SizeType size_type;
+ typedef BucketTraits bucket_traits;
+ static const std::size_t bool_flags = BoolFlags;
+};
+
+template
+ < class UsetOpt
+ , std::size_t BoolMask
+ >
+struct usetopt_mask
+{
+ typedef usetopt
+ <typename UsetOpt::value_traits
+ ,typename UsetOpt::hash
+ ,typename UsetOpt::equal
+ ,typename UsetOpt::size_type
+ ,typename UsetOpt::bucket_traits
+ ,UsetOpt::bool_flags & BoolMask
+ > type;
+};
+
template <class NodeTraits>
struct hash_reduced_slist_node_traits
{
@@ -109,7 +153,6 @@
>::type type;
};
-
template<class SupposedValueTraits>
struct unordered_bucket_impl
{
@@ -173,11 +216,11 @@
template<class Config>
struct bucket_plus_size
: public detail::size_holder
- < Config::constant_time_size
+ < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos)
, typename Config::size_type>
{
typedef detail::size_holder
- < Config::constant_time_size
+ < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos)
, typename Config::size_type> size_traits;
typedef typename Config::bucket_traits bucket_traits;
@@ -188,11 +231,12 @@
};
template<class Config>
-struct bucket_hash_t : public detail::ebo_functor_holder<typename Config::hash>
+struct bucket_hash_t
+ : public detail::ebo_functor_holder<typename Config::hash>
{
typedef typename Config::hash hasher;
typedef detail::size_holder
- < Config::constant_time_size
+ < 0 != (Config::bool_flags & hash_bool_flags::constant_time_size_pos)
, typename Config::size_type> size_traits;
typedef typename Config::bucket_traits bucket_traits;
@@ -236,6 +280,7 @@
template<class Config>
struct hashtable_data_t : public Config::value_traits
{
+ static const std::size_t bool_flags = Config::bool_flags;
typedef typename Config::value_traits value_traits;
typedef typename Config::equal equal;
typedef typename Config::hash hasher;
@@ -243,9 +288,27 @@
hashtable_data_t( const bucket_traits &b_traits, const hasher & h
, const equal &e, const value_traits &val_traits)
- : Config::value_traits(val_traits), bucket_hash_equal_(b_traits, h, e)
+ : Config::value_traits(val_traits), internal_(b_traits, h, e)
{}
- bucket_hash_equal_t<Config, Config::cache_begin> bucket_hash_equal_;
+ typedef typename detail::usetopt_mask
+ < Config
+ , detail::hash_bool_flags::constant_time_size_pos
+ | detail::hash_bool_flags::incremental_pos
+ >::type masked_config_t;
+ struct internal
+ : public detail::size_holder
+ < 0 != (Config::bool_flags & hash_bool_flags::incremental_pos)
+ , typename Config::size_type>
+ {
+ internal(const bucket_traits &b_traits, const hasher & h, const equal &e)
+ : bucket_hash_equal_(b_traits, h, e)
+ {}
+
+ bucket_hash_equal_t
+ < masked_config_t
+ , 0 != (bool_flags & hash_bool_flags::cache_begin_pos)
+ > bucket_hash_equal_;
+ } internal_;
};
struct insert_commit_data_impl
@@ -253,12 +316,154 @@
std::size_t hash;
};
-template <class T>
-struct internal_default_uset_hook
+template<class NodeTraits>
+struct group_functions
{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_uset_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
+ typedef NodeTraits node_traits;
+ typedef unordered_group_adapter<node_traits> group_traits;
+ typedef typename node_traits::node_ptr node_ptr;
+ typedef typename node_traits::node node;
+ typedef typename reduced_slist_node_traits
+ <node_traits>::type reduced_node_traits;
+ typedef typename reduced_node_traits::node_ptr slist_node_ptr;
+ typedef typename reduced_node_traits::node slist_node;
+ typedef circular_slist_algorithms<group_traits> group_algorithms;
+
+ static node_ptr dcast_bucket_ptr(slist_node_ptr p)
+ { return node_ptr(&static_cast<node&>(*p)); }
+
+ static slist_node_ptr priv_get_bucket_before_begin
+ (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p)
+ {
+ //First find the last node of p's group.
+ //This requires checking the first node of the next group or
+ //the bucket node.
+ node_ptr prev_node = p;
+ node_ptr nxt(node_traits::get_next(p));
+ while(!(bucket_beg <= nxt && nxt <= bucket_end) &&
+ (group_traits::get_next(nxt) == prev_node)){
+ prev_node = nxt;
+ nxt = node_traits::get_next(nxt);
+ }
+
+ //If we've reached the bucket node just return it.
+ if(bucket_beg <= nxt && nxt <= bucket_end){
+ return nxt;
+ }
+
+ //Otherwise, iterate using group links until the bucket node
+ node_ptr first_node_of_group = nxt;
+ node_ptr last_node_group = group_traits::get_next(first_node_of_group);
+ slist_node_ptr possible_end = node_traits::get_next(last_node_group);
+
+ while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){
+ first_node_of_group = dcast_bucket_ptr(possible_end);
+ last_node_group = group_traits::get_next(first_node_of_group);
+ possible_end = node_traits::get_next(last_node_group);
+ }
+ return possible_end;
+ }
+
+ static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group)
+ {
+ //Just iterate using group links and obtain the node
+ //before "first_in_group)"
+ node_ptr prev_node = dcast_bucket_ptr(bucket_node);
+ node_ptr nxt(node_traits::get_next(prev_node));
+ while(nxt != first_in_group){
+ prev_node = group_traits::get_next(nxt);
+ nxt = node_traits::get_next(prev_node);
+ }
+ return prev_node;
+ }
+
+ static node_ptr priv_get_first_in_group_of_last_in_group(node_ptr last_in_group)
+ {
+ //Just iterate using group links and obtain the node
+ //before "last_in_group"
+ node_ptr possible_first = group_traits::get_next(last_in_group);
+ node_ptr possible_first_prev = group_traits::get_next(possible_first);
+ // The deleted node is at the end of the group, so the
+ // node in the group pointing to it is at the beginning
+ // of the group. Find that to change its pointer.
+ while(possible_first_prev != last_in_group){
+ possible_first = possible_first_prev;
+ possible_first_prev = group_traits::get_next(possible_first);
+ }
+ return possible_first;
+ }
+
+
+ static void priv_erase_from_group(slist_node_ptr end_ptr, node_ptr to_erase_ptr, detail::true_)
+ {
+ node_ptr nxt_ptr(node_traits::get_next(to_erase_ptr));
+ node_ptr prev_in_group_ptr(group_traits::get_next(to_erase_ptr));
+ bool last_in_group = (end_ptr == nxt_ptr) ||
+ (group_traits::get_next(nxt_ptr) != to_erase_ptr);
+ bool first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr;
+
+ if(first_in_group && last_in_group){
+ group_algorithms::init(to_erase_ptr);
+ }
+ else if(first_in_group){
+ group_algorithms::unlink_after(nxt_ptr);
+ }
+ else if(last_in_group){
+ node_ptr first_in_group =
+ priv_get_first_in_group_of_last_in_group(to_erase_ptr);
+ group_algorithms::unlink_after(first_in_group);
+ }
+ else{
+ group_algorithms::unlink_after(nxt_ptr);
+ }
+ }
+
+ static void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_)
+ {}
+
+ static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_)
+ { return group_traits::get_next(first_in_group); }
+
+ static node_ptr priv_get_last_in_group(node_ptr n, detail::false_)
+ { return n; }
+};
+
+template<class BucketType, class SplitTraits>
+class incremental_rehash_rollback
+{
+ private:
+ typedef BucketType bucket_type;
+ typedef SplitTraits split_traits;
+
+ incremental_rehash_rollback();
+ incremental_rehash_rollback & operator=(const incremental_rehash_rollback &);
+ incremental_rehash_rollback (const incremental_rehash_rollback &);
+
+ public:
+ incremental_rehash_rollback
+ (bucket_type &source_bucket, bucket_type &destiny_bucket, split_traits &split_traits)
+ : source_bucket_(source_bucket), destiny_bucket_(destiny_bucket)
+ , split_traits_(split_traits), released_(false)
+ {}
+
+ void release()
+ { released_ = true; }
+
+ ~incremental_rehash_rollback()
+ {
+ if(!released_){
+ //If an exception is thrown, just put all moved nodes back in the old bucket
+ //and move back the split mark.
+ destiny_bucket_.splice_after(destiny_bucket_.before_begin(), source_bucket_);
+ split_traits_.decrement();
+ }
+ }
+
+ private:
+ bucket_type &source_bucket_;
+ bucket_type &destiny_bucket_;
+ split_traits &split_traits_;
+ bool released_;
};
} //namespace detail {
@@ -304,50 +509,13 @@
typedef implementation_defined type;
};
-template <class T>
-struct get_default_uset_hook
-{
- typedef typename T::default_uset_hook type;
-};
-
-template < class ValueTraits
- , bool UniqueKeys
- , class Hash
- , class Equal
- , class SizeType
- , bool ConstantTimeSize
- , class BucketTraits
- , bool Power2Buckets
- , bool CacheBegin
- , bool CompareHash
- >
-struct usetopt
-{
- typedef ValueTraits value_traits;
- typedef Hash hash;
- typedef Equal equal;
- typedef SizeType size_type;
- typedef BucketTraits bucket_traits;
- static const bool constant_time_size = ConstantTimeSize;
- static const bool power_2_buckets = Power2Buckets;
- static const bool unique_keys = UniqueKeys;
- static const bool cache_begin = CacheBegin;
- static const bool compare_hash = CompareHash;
-};
-
struct default_bucket_traits;
template <class T>
struct uset_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < detail::internal_default_uset_hook<T>::value
- , get_default_uset_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_uset_hook>
, constant_time_size<true>
, size_type<std::size_t>
, equal<std::equal_to<T> >
@@ -356,6 +524,7 @@
, power_2_buckets<false>
, cache_begin<false>
, compare_hash<false>
+ , incremental<false>
>::type
{};
@@ -380,7 +549,7 @@
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<>
-//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>.
+//! \c bucket_traits<>, power_2_buckets<>, cache_begin<> and incremental<>.
//!
//! hashtable only provides forward iterators but it provides 4 iterator types:
//! iterator and const_iterator to navigate through the whole container and
@@ -397,13 +566,12 @@
//!
//! Since no automatic rehashing is done, iterators are never invalidated when
//! inserting or erasing elements. Iterators are only invalidated when rehashing.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
class hashtable_impl
- : private detail::hashtable_data_t<Config>
{
public:
typedef typename Config::value_traits value_traits;
@@ -455,18 +623,22 @@
<node_ptr, const node>::type const_node_ptr;
typedef typename slist_impl::node_algorithms node_algorithms;
- static const bool constant_time_size = Config::constant_time_size;
static const bool stateful_value_traits = detail::store_cont_ptr_on_it<hashtable_impl>::value;
static const bool store_hash = detail::store_hash_is_true<node_traits>::value;
- static const bool unique_keys = Config::unique_keys;
+
+ static const bool unique_keys = 0 != (Config::bool_flags & detail::hash_bool_flags::unique_keys_pos);
+ static const bool constant_time_size = 0 != (Config::bool_flags & detail::hash_bool_flags::constant_time_size_pos);
+ static const bool cache_begin = 0 != (Config::bool_flags & detail::hash_bool_flags::cache_begin_pos);
+ static const bool compare_hash = 0 != (Config::bool_flags & detail::hash_bool_flags::compare_hash_pos);
+ static const bool incremental = 0 != (Config::bool_flags & detail::hash_bool_flags::incremental_pos);
+ static const bool power_2_buckets = incremental || (0 != (Config::bool_flags & detail::hash_bool_flags::power_2_buckets_pos));
+
static const bool optimize_multikey
= detail::optimize_multikey_is_true<node_traits>::value && !unique_keys;
- static const bool power_2_buckets = Config::power_2_buckets;
- static const bool cache_begin = Config::cache_begin;
- static const bool compare_hash = Config::compare_hash;
/// @cond
private:
+
//Configuration error: compare_hash<> can't be specified without store_hash<>
//See documentation for more explanations
BOOST_STATIC_ASSERT((!compare_hash || store_hash));
@@ -483,7 +655,17 @@
typedef detail::bool_<cache_begin> cache_begin_t;
typedef detail::bool_<power_2_buckets> power_2_buckets_t;
typedef detail::size_holder<constant_time_size, size_type> size_traits;
- typedef detail::hashtable_data_t<Config> base_type;
+ typedef detail::size_holder<incremental, size_type> split_traits;
+ typedef detail::group_functions<node_traits> group_functions_t;
+
+ static const std::size_t hashtable_data_bool_flags_mask =
+ ( detail::hash_bool_flags::cache_begin_pos
+ | detail::hash_bool_flags::constant_time_size_pos
+ | detail::hash_bool_flags::incremental_pos
+ );
+ typedef typename detail::usetopt_mask
+ <Config, hashtable_data_bool_flags_mask>::type masked_config_t;
+ detail::hashtable_data_t<masked_config_t> data_;
template<bool IsConst>
struct downcast_node_to_value
@@ -555,16 +737,16 @@
/// @cond
const real_value_traits &get_real_value_traits(detail::bool_<false>) const
- { return *this; }
+ { return this->data_; }
const real_value_traits &get_real_value_traits(detail::bool_<true>) const
- { return base_type::get_value_traits(*this); }
+ { return data_.get_value_traits(*this); }
real_value_traits &get_real_value_traits(detail::bool_<false>)
- { return *this; }
+ { return this->data_; }
real_value_traits &get_real_value_traits(detail::bool_<true>)
- { return base_type::get_value_traits(*this); }
+ { return data_.get_value_traits(*this); }
/// @endcond
@@ -593,14 +775,16 @@
, const hasher & hash_func = hasher()
, const key_equal &equal_func = key_equal()
, const value_traits &v_traits = value_traits())
- : base_type(b_traits, hash_func, equal_func, v_traits)
+ : data_(b_traits, hash_func, equal_func, v_traits)
{
priv_initialize_buckets();
this->priv_size_traits().set_size(size_type(0));
- BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_buckets_len() != 0);
+ size_type bucket_size = this->priv_buckets_len();
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_size != 0);
//Check power of two bucket array if the option is activated
BOOST_INTRUSIVE_INVARIANT_ASSERT
- (!power_2_buckets || (0 == (this->priv_buckets_len() & (this->priv_buckets_len()-1))));
+ (!power_2_buckets || (0 == (bucket_size & (bucket_size-1))));
+ priv_split_traits().set_size(bucket_size>>1);
}
//! <b>Effects</b>: Detaches all elements from this. The objects in the unordered_set
@@ -620,10 +804,7 @@
//!
//! <b>Throws</b>: Nothing.
iterator begin()
- {
- size_type bucket_num;
- return iterator(this->priv_begin(bucket_num), this);
- }
+ { return iterator(this->priv_begin(), this); }
//! <b>Effects</b>: Returns a const_iterator pointing to the beginning
//! of the unordered_set.
@@ -643,10 +824,7 @@
//!
//! <b>Throws</b>: Nothing.
const_iterator cbegin() const
- {
- size_type bucket_num;
- return const_iterator(this->priv_begin(bucket_num), this);
- }
+ { return const_iterator(this->priv_begin(), this); }
//! <b>Effects</b>: Returns an iterator pointing to the end of the unordered_set.
//!
@@ -760,21 +938,32 @@
this->priv_size_traits().set_size(other.priv_size_traits().get_size());
other.priv_size_traits().set_size(backup);
}
+ else if(incremental){
+ size_type backup = this->priv_split_traits().get_size();
+ this->priv_split_traits().set_size(other.priv_split_traits().get_size());
+ other.priv_split_traits().set_size(backup);
+ }
}
- //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw
+ //! Cloner should yield to nodes that compare equal and produce the same
+ //! hash than the original node.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. The hash function and the equality
+ //! predicate are copied from the source.
//!
- //! If cloner throws, all cloned elements are unlinked and disposed
+ //! If store_hash option is true, this method does not use the hash function.
+ //!
+ //! If any operation throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
- //!
+ //!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner or hasher throw or hash or equality predicate copying
+ //! throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const hashtable_impl &src, Cloner cloner, Disposer disposer)
{
@@ -789,7 +978,7 @@
(!power_2_buckets || (0 == (dst_bucket_count & (dst_bucket_count-1))));
//If src bucket count is bigger or equal, structural copy is possible
- if(src_bucket_count >= dst_bucket_count){
+ if(!incremental && (src_bucket_count >= dst_bucket_count)){
//First clone the first ones
const bucket_ptr src_buckets = src.priv_buckets();
const bucket_ptr dst_buckets = this->priv_buckets();
@@ -813,7 +1002,7 @@
; constructed < src_bucket_count
; ++constructed){
bucket_type &dst_b =
- dst_buckets[priv_hash_to_bucket(constructed, dst_bucket_count)];
+ dst_buckets[priv_hash_to_bucket(constructed, dst_bucket_count, dst_bucket_count)];
bucket_type &src_b = src_buckets[constructed];
for( siterator b(src_b.begin()), e(src_b.end())
; b != e
@@ -822,14 +1011,29 @@
}
}
}
+ this->priv_hasher() = src.priv_hasher();
+ this->priv_equal() = src.priv_equal();
rollback.release();
this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ this->priv_split_traits().set_size(dst_bucket_count);
priv_insertion_update_cache(0u);
priv_erasure_update_cache();
}
+ else if(store_hash){
+ //Unlike previous cloning algorithm, this can throw
+ //if cloner, hasher or comparison functor throw
+ const_iterator b(src.begin()), e(src.end());
+ detail::exception_disposer<hashtable_impl, Disposer>
+ rollback(*this, disposer);
+ for(; b != e; ++b){
+ std::size_t hash_value = this->priv_stored_or_compute_hash(*b, store_hash_t());;
+ this->priv_insert_equal_with_hash(*cloner(*b), hash_value);
+ }
+ rollback.release();
+ }
else{
//Unlike previous cloning algorithm, this can throw
- //if cloner, the hasher or comparison functor throw
+ //if cloner, hasher or comparison functor throw
const_iterator b(src.begin()), e(src.end());
detail::exception_disposer<hashtable_impl, Disposer>
rollback(*this, disposer);
@@ -848,23 +1052,7 @@
siterator prev;
siterator it = this->priv_find
(value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev);
- bucket_type &b = this->priv_buckets()[bucket_num];
- bool found_equal = it != priv_invalid_local_it();
- node_ptr n = node_ptr(&priv_value_to_node(value));
- this->priv_store_hash(n, hash_value, store_hash_t());
- if(safemode_or_autounlink)
- BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
- if(!found_equal){
- it = b.before_begin();
- }
- if(optimize_multikey){
- node_ptr first_in_group = found_equal ?
- dcast_bucket_ptr(it.pointed_node()) : node_ptr(0);
- this->priv_insert_in_group(first_in_group, n, optimize_multikey_t());
- }
- priv_insertion_update_cache(bucket_num);
- this->priv_size_traits().increment();
- return iterator(b.insert_after(it, *n), this);
+ return priv_insert_equal_find(value, bucket_num, hash_value, it);
}
template<class Iterator>
@@ -968,7 +1156,7 @@
this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev);
bool success = prev_pos == priv_invalid_local_it();
if(success){
- prev_pos = this->priv_buckets()[bucket_num].before_begin();
+ prev_pos = prev;
}
return std::pair<iterator, bool>(iterator(prev_pos, this),success);
}
@@ -1177,8 +1365,8 @@
}
else if(optimize_multikey){
siterator last = bucket_type::s_iterator_to
- (*node_traits::get_next(priv_get_last_in_group
- (dcast_bucket_ptr(it.pointed_node()))));
+ (*node_traits::get_next(group_functions_t::priv_get_last_in_group
+ (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())));
this->priv_erase_range_impl(bucket_num, prev, last, disposer, count);
}
else{
@@ -1188,7 +1376,7 @@
slist_node_ptr n(it.pointed_node());
const value_type &v = priv_value_from_slist_node(n);
if(compare_hash){
- std::size_t vh = this->priv_stored_hash(v, store_hash_t());
+ std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t());
if(h != vh || !equal_func(key, v)){
break;
}
@@ -1676,9 +1864,15 @@
//! or the same as the old bucket array. new_size is the length of the
//! the array pointed by new_buckets. If new_buckets == this->bucket_pointer()
//! n can be bigger or smaller than this->bucket_count().
+ //! 'new_bucket_traits' copy constructor should not throw.
//!
//! <b>Effects</b>: Updates the internal reference with the new bucket erases
- //! the values from the old bucket and inserts then in the new one.
+ //! the values from the old bucket and inserts then in the new one.
+ //! Bucket traits hold by *this is assigned from new_bucket_traits.
+ //! If the container is configured as incremental<>, the split bucket is set
+ //! to the new bucket_len().
+ //!
+ //! If store_hash option is true, this method does not use the hash function.
//!
//! <b>Complexity</b>: Average case linear in this->size(), worst case quadratic.
//!
@@ -1698,7 +1892,7 @@
const bool same_buffer = old_buckets == new_buckets;
//If the new bucket length is a common factor
//of the old one we can avoid hash calculations.
- const bool fast_shrink = (old_buckets_len > new_buckets_len) &&
+ const bool fast_shrink = (!incremental) && (old_buckets_len > new_buckets_len) &&
(power_2_buckets ||(old_buckets_len % new_buckets_len) == 0);
//If we are shrinking the same bucket array and it's
//is a fast shrink, just rehash the last nodes
@@ -1708,7 +1902,9 @@
new_first_bucket_num = priv_get_cache_bucket_num();
}
- //Anti-exception stuff: they destroy the elements if something goes wrong
+ //Anti-exception stuff: they destroy the elements if something goes wrong.
+ //If the source and destination buckets are the same, the second rollback function
+ //is harmless, because all elements have been already unlinked and destroyed
typedef detail::init_disposer<node_algorithms> NodeDisposer;
NodeDisposer node_disp;
detail::exception_array_disposer<bucket_type, NodeDisposer>
@@ -1733,12 +1929,13 @@
siterator i(old_bucket.begin());
for(;i != end; ++i){
const value_type &v = priv_value_from_slist_node(i.pointed_node());
- const std::size_t hash_value = this->priv_stored_hash(v, store_hash_t());
- const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len);
+ const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t());
+ const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len, new_buckets_len);
if(cache_begin && new_n < new_first_bucket_num)
new_first_bucket_num = new_n;
siterator last = bucket_type::s_iterator_to
- (*priv_get_last_in_group(dcast_bucket_ptr(i.pointed_node())));
+ (*group_functions_t::priv_get_last_in_group
+ (dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t()));
if(same_buffer && new_n == n){
before_i = last;
}
@@ -1750,7 +1947,7 @@
}
}
else{
- const size_type new_n = priv_hash_to_bucket(n, new_buckets_len);
+ const size_type new_n = priv_hash_to_bucket(n, new_buckets_len, new_buckets_len);
if(cache_begin && new_n < new_first_bucket_num)
new_first_bucket_num = new_n;
bucket_type &new_b = new_buckets[new_n];
@@ -1764,14 +1961,148 @@
}
this->priv_size_traits().set_size(size_backup);
+ this->priv_split_traits().set_size(new_buckets_len);
this->priv_real_bucket_traits() = new_bucket_traits;
priv_initialize_cache();
priv_insertion_update_cache(new_first_bucket_num);
- //priv_erasure_update_cache();
rollback1.release();
rollback2.release();
}
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ //!
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(bool grow = true)
+ {
+ //This function is only available for containers with incremental hashing
+ BOOST_STATIC_ASSERT(( incremental && power_2_buckets ));
+ size_type split_idx = priv_split_traits().get_size();
+ size_type bucket_len = priv_buckets_len();
+
+ if(grow){
+ //Test if the split variable can be changed
+ if(split_idx >= bucket_len)
+ return false;
+
+ size_type bucket_len = priv_buckets_len();
+ size_type bucket_to_rehash = split_idx - bucket_len/2;
+ bucket_type &old_bucket = this->priv_buckets()[bucket_to_rehash];
+ siterator before_i(old_bucket.before_begin());
+ siterator end(old_bucket.end());
+ siterator i(old_bucket.begin());
+ priv_split_traits().increment();
+
+ //Anti-exception stuff: if an exception is thrown while
+ //moving elements from old_bucket to the target bucket, all moved
+ //elements are moved back to the original one.
+ detail::incremental_rehash_rollback<bucket_type, split_traits> rollback
+ ( this->priv_buckets()[split_idx], old_bucket, priv_split_traits());
+ for(;i != end; ++i){
+ const value_type &v = priv_value_from_slist_node(i.pointed_node());
+ const std::size_t hash_value = this->priv_stored_or_compute_hash(v, store_hash_t());
+ const size_type new_n = priv_hash_to_bucket(hash_value);
+ siterator last = bucket_type::s_iterator_to
+ (*group_functions_t::priv_get_last_in_group
+ (dcast_bucket_ptr(i.pointed_node()), optimize_multikey_t()));
+ if(new_n == bucket_to_rehash){
+ before_i = last;
+ }
+ else{
+ bucket_type &new_b = this->priv_buckets()[new_n];
+ new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last);
+ }
+ i = before_i;
+ }
+ rollback.release();
+ priv_erasure_update_cache();
+ return true;
+ }
+ else{
+ //Test if the split variable can be changed
+ if(split_idx <= bucket_len/2)
+ return false;
+ const size_type target_bucket_num = split_idx - 1 - bucket_len/2;
+ bucket_type &target_bucket = this->priv_buckets()[target_bucket_num];
+ bucket_type &source_bucket = this->priv_buckets()[split_idx-1];
+ target_bucket.splice_after(target_bucket.cbefore_begin(), source_bucket);
+ priv_split_traits().decrement();
+ priv_insertion_update_cache(target_bucket_num);
+ return true;
+ }
+ }
+
+ //! <b>Effects</b>: If new_bucket_traits.bucket_count() is not
+ //! this->bucket_count()/2 or this->bucket_count()*2, or
+ //! this->split_bucket() != new_bucket_traits.bucket_count() returns false
+ //! and does nothing.
+ //!
+ //! Otherwise, copy assigns new_bucket_traits to the internal bucket_traits
+ //! and transfers all the objects from old buckets to the new ones.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(const bucket_traits &new_bucket_traits)
+ {
+ //This function is only available for containers with incremental hashing
+ BOOST_STATIC_ASSERT(( incremental && power_2_buckets ));
+ size_type new_bucket_traits_size = new_bucket_traits.bucket_count();
+ size_type cur_bucket_traits = this->priv_buckets_len();
+ if(new_bucket_traits_size/2 != cur_bucket_traits && new_bucket_traits_size != cur_bucket_traits/2){
+ return false;
+ }
+
+ const size_type split_idx = this->split_count();
+
+ if(new_bucket_traits_size/2 == cur_bucket_traits){
+ //Test if the split variable can be changed
+ if(!(split_idx >= cur_bucket_traits))
+ return false;
+ }
+ else{
+ //Test if the split variable can be changed
+ if(!(split_idx <= cur_bucket_traits/2))
+ return false;
+ }
+
+ const size_type ini_n = priv_get_cache_bucket_num();
+ const bucket_ptr old_buckets = this->priv_buckets();
+ this->priv_real_bucket_traits() = new_bucket_traits;
+ if(new_bucket_traits.bucket_begin() != old_buckets){
+ for(size_type n = ini_n; n < split_idx; ++n){
+ bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n];
+ bucket_type &old_bucket = old_buckets[n];
+ new_bucket.splice_after(new_bucket.cbefore_begin(), old_bucket);
+ }
+ //Put cache to safe position
+ priv_initialize_cache();
+ priv_insertion_update_cache(ini_n);
+ }
+ return true;
+ }
+
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ size_type split_count() const
+ {
+ //This function is only available if incremental hashing is activated
+ BOOST_STATIC_ASSERT(( incremental && power_2_buckets ));
+ return this->priv_split_traits().get_size();
+ }
+
//! <b>Effects</b>: Returns the nearest new bucket count optimized for
//! the container that is bigger than n. This suggestion can be used
//! to create bucket arrays with a size that will usually improve
@@ -1812,29 +2143,30 @@
/// @cond
private:
- std::size_t priv_hash_to_bucket(std::size_t hash_value) const
- { return priv_hash_to_bucket(hash_value, power_2_buckets_t()); }
-
- std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_<false>) const
- { return hash_value % this->priv_real_bucket_traits().bucket_count(); }
- std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_<true>) const
- { return hash_value & (this->priv_real_bucket_traits().bucket_count() - 1); }
+ std::size_t priv_hash_to_bucket(std::size_t hash_value) const
+ { return priv_hash_to_bucket(hash_value, this->priv_real_bucket_traits().bucket_count(), priv_split_traits().get_size()); }
- std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len) const
- { return priv_hash_to_bucket(hash_value, bucket_len, power_2_buckets_t()); }
+ std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, std::size_t split) const
+ {
+ std::size_t bucket_number = priv_hash_to_bucket_impl(hash_value, bucket_len, power_2_buckets_t());
+ if(incremental)
+ if(bucket_number >= split)
+ bucket_number -= bucket_len/2;
+ return bucket_number;
+ }
- std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_<false>) const
+ std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_len, detail::bool_<false>) const
{ return hash_value % bucket_len; }
- std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_<true>) const
+ std::size_t priv_hash_to_bucket_impl(std::size_t hash_value, std::size_t bucket_len, detail::bool_<true>) const
{ return hash_value & (bucket_len - 1); }
const key_equal &priv_equal() const
- { return static_cast<const key_equal&>(this->bucket_hash_equal_.get()); }
+ { return static_cast<const key_equal&>(this->data_.internal_.bucket_hash_equal_.get()); }
key_equal &priv_equal()
- { return static_cast<key_equal&>(this->bucket_hash_equal_.get()); }
+ { return static_cast<key_equal&>(this->data_.internal_.bucket_hash_equal_.get()); }
value_type &priv_value_from_slist_node(slist_node_ptr n)
{ return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); }
@@ -1843,16 +2175,16 @@
{ return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); }
const real_bucket_traits &priv_real_bucket_traits(detail::bool_<false>) const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
const real_bucket_traits &priv_real_bucket_traits(detail::bool_<true>) const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
real_bucket_traits &priv_real_bucket_traits(detail::bool_<false>)
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; }
real_bucket_traits &priv_real_bucket_traits(detail::bool_<true>)
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); }
const real_bucket_traits &priv_real_bucket_traits() const
{ return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
@@ -1861,10 +2193,10 @@
{ return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
const hasher &priv_hasher() const
- { return static_cast<const hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
+ { return static_cast<const hasher&>(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); }
hasher &priv_hasher()
- { return static_cast<hasher&>(this->bucket_hash_equal_.bucket_hash.get()); }
+ { return static_cast<hasher&>(this->data_.internal_.bucket_hash_equal_.bucket_hash.get()); }
bucket_ptr priv_buckets() const
{ return this->priv_real_bucket_traits().bucket_begin(); }
@@ -1882,10 +2214,16 @@
{ return *this->get_real_value_traits().to_node_ptr(v); }
size_traits &priv_size_traits()
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
const size_traits &priv_size_traits() const
- { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+ { return this->data_.internal_.bucket_hash_equal_.bucket_hash.bucket_plus_size_; }
+
+ split_traits &priv_split_traits()
+ { return this->data_.internal_; }
+
+ const split_traits &priv_split_traits() const
+ { return this->data_.internal_; }
template<class Disposer>
void priv_erase_range_impl
@@ -1903,7 +2241,7 @@
++to_erase;
slist_node_ptr end_ptr = end.pointed_node();
while(to_erase != end){
- priv_erase_from_group(end_ptr, dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t());
+ group_functions_t::priv_erase_from_group(end_ptr, dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t());
to_erase = b.erase_after_and_dispose(before_first_it, make_node_disposer(disposer));
++num_erased;
}
@@ -1955,10 +2293,10 @@
static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p)
{ return node_ptr(&static_cast<node&>(*p)); }
- std::size_t priv_stored_hash(const value_type &v, detail::true_) const
+ std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const
{ return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); }
- std::size_t priv_stored_hash(const value_type &v, detail::false_) const
+ std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const
{ return priv_hasher()(v); }
std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) const
@@ -2002,10 +2340,10 @@
std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_)
{ return priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); }
- std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::true_)
+ std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::true_)
{
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1);
- slist_node_ptr bb = priv_get_bucket_before_begin
+ slist_node_ptr bb = group_functions_t::priv_get_bucket_before_begin
( f->end().pointed_node()
, l->end().pointed_node()
, dcast_bucket_ptr(it.pointed_node()));
@@ -2016,7 +2354,7 @@
return static_cast<size_type>(&b - &*f);
}
- std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::false_)
+ std::size_t priv_get_bucket_num_no_hash_store(siterator it, detail::false_)
{
bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1);
slist_node_ptr first_ptr(f->cend().pointed_node())
@@ -2035,34 +2373,6 @@
return static_cast<std::size_t>(&b - &*f);
}
- void priv_erase_from_group(slist_node_ptr end_ptr, node_ptr to_erase_ptr, detail::true_)
- {
- node_ptr nxt_ptr(node_traits::get_next(to_erase_ptr));
- node_ptr prev_in_group_ptr(group_traits::get_next(to_erase_ptr));
- bool last_in_group = (end_ptr == nxt_ptr) ||
- (group_traits::get_next(nxt_ptr) != to_erase_ptr);
- bool first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr;
-
- if(first_in_group && last_in_group){
- group_algorithms::init(to_erase_ptr);
- }
- else if(first_in_group){
- group_algorithms::unlink_after(nxt_ptr);
- }
- else if(last_in_group){
- node_ptr first_in_group = //possible_first_in_group ? possible_first_in_group :
- priv_get_first_in_group_of_last_in_group(to_erase_ptr);
- group_algorithms::unlink_after(first_in_group);
- //possible_first_in_group = 0;
- }
- else{
- group_algorithms::unlink_after(nxt_ptr);
- }
- }
-
- void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_)
- {}
-
void priv_init_group(slist_node_ptr n, detail::true_)
{ group_algorithms::init(dcast_bucket_ptr(n)); }
@@ -2083,79 +2393,9 @@
}
}
- static slist_node_ptr priv_get_bucket_before_begin
- (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p)
- {
- //First find the last node of p's group.
- //This requires checking the first node of the next group or
- //the bucket node.
- node_ptr prev_node = p;
- node_ptr nxt(node_traits::get_next(p));
- while(!(bucket_beg <= nxt && nxt <= bucket_end) &&
- (group_traits::get_next(nxt) == prev_node)){
- prev_node = nxt;
- nxt = node_traits::get_next(nxt);
- }
-
- //If we've reached the bucket node just return it.
- if(bucket_beg <= nxt && nxt <= bucket_end){
- return nxt;
- }
-
- //Otherwise, iterate using group links until the bucket node
- node_ptr first_node_of_group = nxt;
- node_ptr last_node_group = group_traits::get_next(first_node_of_group);
- slist_node_ptr possible_end = node_traits::get_next(last_node_group);
-
- while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){
- first_node_of_group = dcast_bucket_ptr(possible_end);
- last_node_group = group_traits::get_next(first_node_of_group);
- possible_end = node_traits::get_next(last_node_group);
- }
- return possible_end;
- }
-
- static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group)
- {
- //Just iterate using group links and obtain the node
- //before "first_in_group)"
- node_ptr prev_node = dcast_bucket_ptr(bucket_node);
- node_ptr nxt(node_traits::get_next(prev_node));
- while(nxt != first_in_group){
- prev_node = group_traits::get_next(nxt);
- nxt = node_traits::get_next(prev_node);
- }
- return prev_node;
- }
-
- static node_ptr priv_get_first_in_group_of_last_in_group(node_ptr last_in_group)
- {
- //Just iterate using group links and obtain the node
- //before "last_in_group"
- node_ptr possible_first = group_traits::get_next(last_in_group);
- node_ptr possible_first_prev = group_traits::get_next(possible_first);
- // The deleted node is at the end of the group, so the
- // node in the group pointing to it is at the beginning
- // of the group. Find that to change its pointer.
- while(possible_first_prev != last_in_group){
- possible_first = possible_first_prev;
- possible_first_prev = group_traits::get_next(possible_first);
- }
- return possible_first;
- }
-
void priv_insert_in_group(node_ptr, node_ptr, detail::false_)
{}
- static node_ptr priv_get_last_in_group(node_ptr first_in_group)
- { return priv_get_last_in_group(first_in_group, optimize_multikey_t()); }
-
- static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_)
- { return group_traits::get_next(first_in_group); }
-
- static node_ptr priv_get_last_in_group(node_ptr n, detail::false_)
- { return n; }
-
siterator priv_get_previous
(bucket_type &b, siterator i)
{ return priv_get_previous(b, i, optimize_multikey_t()); }
@@ -2166,9 +2406,8 @@
node_ptr elem(dcast_bucket_ptr(i.pointed_node()));
node_ptr prev_in_group(group_traits::get_next(elem));
bool first_in_group = node_traits::get_next(prev_in_group) != elem;
-
typename bucket_type::node &n = first_in_group
- ? *priv_get_prev_to_first_in_group(b.end().pointed_node(), elem)
+ ? *group_functions_t::priv_get_prev_to_first_in_group(b.end().pointed_node(), elem)
: *group_traits::get_next(elem)
;
return bucket_type::s_iterator_to(n);
@@ -2234,15 +2473,15 @@
].before_begin().pointed_node();
}
else{
- bucket_node = priv_get_bucket_before_begin
+ bucket_node = group_functions_t::priv_get_bucket_before_begin
(first_end_ptr, last_end_ptr, start_pos);
}
prev = bucket_type::s_iterator_to
- (*priv_get_prev_to_first_in_group(bucket_node, elem));
+ (*group_functions_t::priv_get_prev_to_first_in_group(bucket_node, elem));
}
else{
if(last_in_group){
- nxt_in_group = priv_get_first_in_group_of_last_in_group(elem);
+ nxt_in_group = group_functions_t::priv_get_first_in_group_of_last_in_group(elem);
}
else{
nxt_in_group = node_traits::get_next(elem);
@@ -2283,32 +2522,29 @@
siterator priv_invalid_local_it() const
{ return priv_invalid_bucket()->end(); }
- siterator priv_begin(size_type &bucket_num) const
- { return priv_begin(bucket_num, cache_begin_t()); }
+ siterator priv_begin() const
+ { return priv_begin(cache_begin_t()); }
- siterator priv_begin(size_type &bucket_num, detail::bool_<false>) const
+ siterator priv_begin(detail::bool_<false>) const
{
size_type n = 0;
size_type buckets_len = this->priv_buckets_len();
for (n = 0; n < buckets_len; ++n){
bucket_type &b = this->priv_buckets()[n];
if(!b.empty()){
- bucket_num = n;
return b.begin();
}
}
- bucket_num = n;
return priv_invalid_local_it();
}
- siterator priv_begin(size_type &bucket_num, detail::bool_<true>) const
+ siterator priv_begin(detail::bool_<true>) const
{
- bucket_num = this->bucket_hash_equal_.cached_begin_ - this->priv_buckets();
- if(this->bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){
+ if(this->data_.internal_.bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){
return priv_invalid_local_it();
}
else{
- return this->bucket_hash_equal_.cached_begin_->begin();
+ return this->data_.internal_.bucket_hash_equal_.cached_begin_->begin();
}
}
@@ -2316,7 +2552,7 @@
{ priv_initialize_cache(cache_begin_t()); }
void priv_initialize_cache(detail::bool_<true>)
- { this->bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); }
+ { this->data_.internal_.bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); }
void priv_initialize_cache(detail::bool_<false>)
{}
@@ -2327,8 +2563,8 @@
void priv_insertion_update_cache(size_type insertion_bucket, detail::bool_<true>)
{
bucket_ptr p = priv_buckets() + insertion_bucket;
- if(p < this->bucket_hash_equal_.cached_begin_){
- this->bucket_hash_equal_.cached_begin_ = p;
+ if(p < this->data_.internal_.bucket_hash_equal_.cached_begin_){
+ this->data_.internal_.bucket_hash_equal_.cached_begin_ = p;
}
}
@@ -2361,11 +2597,11 @@
priv_initialize_cache();
}
else{
- size_type current_n = this->bucket_hash_equal_.cached_begin_ - priv_buckets();
+ size_type current_n = this->data_.internal_.bucket_hash_equal_.cached_begin_ - priv_buckets();
for( const size_type num_buckets = this->priv_buckets_len()
; current_n < num_buckets
- ; ++current_n, ++this->bucket_hash_equal_.cached_begin_){
- if(!this->bucket_hash_equal_.cached_begin_->empty()){
+ ; ++current_n, ++this->data_.internal_.bucket_hash_equal_.cached_begin_){
+ if(!this->data_.internal_.bucket_hash_equal_.cached_begin_->empty()){
return;
}
}
@@ -2378,8 +2614,8 @@
void priv_swap_cache(detail::bool_<true>, hashtable_impl &other)
{
- std::swap( this->bucket_hash_equal_.cached_begin_
- , other.bucket_hash_equal_.cached_begin_);
+ std::swap( this->data_.internal_.bucket_hash_equal_.cached_begin_
+ , other.data_.internal_.bucket_hash_equal_.cached_begin_);
}
void priv_swap_cache(detail::bool_<false>, hashtable_impl &)
@@ -2389,7 +2625,7 @@
{ return priv_get_cache(cache_begin_t()); }
bucket_ptr priv_get_cache(detail::bool_<true>)
- { return this->bucket_hash_equal_.cached_begin_; }
+ { return this->data_.internal_.bucket_hash_equal_.cached_begin_; }
bucket_ptr priv_get_cache(detail::bool_<false>)
{ return this->priv_buckets(); }
@@ -2398,7 +2634,7 @@
{ priv_set_cache(p, cache_begin_t()); }
void priv_set_cache(bucket_ptr p, detail::bool_<true>)
- { this->bucket_hash_equal_.cached_begin_ = p; }
+ { this->data_.internal_.bucket_hash_equal_.cached_begin_ = p; }
void priv_set_cache(bucket_ptr, detail::bool_<false>)
{}
@@ -2407,7 +2643,7 @@
{ return priv_get_cache_bucket_num(cache_begin_t()); }
size_type priv_get_cache_bucket_num(detail::bool_<true>)
- { return this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); }
+ { return this->data_.internal_.bucket_hash_equal_.cached_begin_ - this->priv_buckets(); }
size_type priv_get_cache_bucket_num(detail::bool_<false>)
{ return 0u; }
@@ -2420,10 +2656,7 @@
}
void priv_initialize_buckets()
- {
- this->priv_clear_buckets
- ( priv_buckets(), this->priv_buckets_len());
- }
+ { this->priv_clear_buckets(priv_buckets(), this->priv_buckets_len()); }
void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len)
{
@@ -2444,21 +2677,28 @@
( const KeyType &key, KeyHasher hash_func
, KeyValueEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const
{
- bucket_number = priv_hash_to_bucket((h = hash_func(key)));
+ h = hash_func(key);
+ return priv_find_with_hash(key, equal_func, bucket_number, h, previt);
+ }
+ template<class KeyType, class KeyValueEqual>
+ siterator priv_find_with_hash
+ ( const KeyType &key, KeyValueEqual equal_func, size_type &bucket_number, const std::size_t h, siterator &previt) const
+ {
+ bucket_number = priv_hash_to_bucket(h);
+ bucket_type &b = this->priv_buckets()[bucket_number];
+ previt = b.before_begin();
if(constant_time_size && this->empty()){
return priv_invalid_local_it();
}
- bucket_type &b = this->priv_buckets()[bucket_number];
- previt = b.before_begin();
siterator it = previt;
++it;
while(it != b.end()){
const value_type &v = priv_value_from_slist_node(it.pointed_node());
if(compare_hash){
- std::size_t vh = this->priv_stored_hash(v, store_hash_t());
+ std::size_t vh = this->priv_stored_or_compute_hash(v, store_hash_t());
if(h == vh && equal_func(key, v)){
return it;
}
@@ -2468,7 +2708,8 @@
}
if(optimize_multikey){
previt = bucket_type::s_iterator_to
- (*priv_get_last_in_group(dcast_bucket_ptr(it.pointed_node())));
+ (*group_functions_t::priv_get_last_in_group
+ (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t()));
it = previt;
}
else{
@@ -2476,10 +2717,45 @@
}
++it;
}
-
+ previt = b.before_begin();
return priv_invalid_local_it();
}
+ iterator priv_insert_equal_with_hash(reference value, std::size_t hash_value)
+ {
+ size_type bucket_num;
+ siterator prev;
+ siterator it = this->priv_find_with_hash
+ (value, this->priv_equal(), bucket_num, hash_value, prev);
+ return priv_insert_equal_find(value, bucket_num, hash_value, it);
+ }
+
+ iterator priv_insert_equal_find(reference value, size_type bucket_num, std::size_t hash_value, siterator it)
+ {
+ bucket_type &b = this->priv_buckets()[bucket_num];
+ bool found_equal = it != priv_invalid_local_it();
+ if(!found_equal){
+ it = b.before_begin();
+ }
+ //Now store hash if needed
+ node_ptr n = node_ptr(&priv_value_to_node(value));
+ this->priv_store_hash(n, hash_value, store_hash_t());
+ //Checks for some modes
+ if(safemode_or_autounlink)
+ BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n));
+ //Shorcut for optimize_multikey cases
+ if(optimize_multikey){
+ node_ptr first_in_group = found_equal ?
+ dcast_bucket_ptr(it.pointed_node()) : node_ptr(0);
+ this->priv_insert_in_group(first_in_group, n, optimize_multikey_t());
+ }
+ //Update cache and increment size if needed
+ priv_insertion_update_cache(bucket_num);
+ this->priv_size_traits().increment();
+ //Insert the element in the bucket after it
+ return iterator(b.insert_after(it, *n), this);
+ }
+
template<class KeyType, class KeyHasher, class KeyValueEqual>
std::pair<siterator, siterator> priv_equal_range
( const KeyType &key
@@ -2506,8 +2782,8 @@
siterator it = to_return.first;
if(optimize_multikey){
to_return.second = bucket_type::s_iterator_to
- (*node_traits::get_next(priv_get_last_in_group
- (dcast_bucket_ptr(it.pointed_node()))));
+ (*node_traits::get_next(group_functions_t::priv_get_last_in_group
+ (dcast_bucket_ptr(it.pointed_node()), optimize_multikey_t())));
count = std::distance(it, to_return.second);
if(to_return.second != b.end()){
bucket_number_second = bucket_number_first;
@@ -2520,7 +2796,7 @@
while(it != b.end()){
const value_type &v = priv_value_from_slist_node(it.pointed_node());
if(compare_hash){
- std::size_t hv = this->priv_stored_hash(v, store_hash_t());
+ std::size_t hv = this->priv_stored_or_compute_hash(v, store_hash_t());
if(hv != h || !equal_func(key, v)){
to_return.second = it;
bucket_number_second = bucket_number_first;
@@ -2556,18 +2832,28 @@
};
/// @cond
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template < class T
, bool UniqueKeys
, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
, class O5 = none, class O6 = none
, class O7 = none, class O8 = none
- , class O9 = none
+ , class O9 = none, class O10= none
>
+#else
+template <class T, bool UniqueKeys, class ...Options>
+#endif
struct make_hashtable_opt
{
typedef typename pack_options
- < uset_defaults<T>, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type packed_options;
+ < uset_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type packed_options;
//Real value traits must be calculated from options
typedef typename detail::get_value_traits
@@ -2598,31 +2884,32 @@
, specified_bucket_traits
>::type real_bucket_traits;
- typedef usetopt
+ typedef detail::usetopt
< value_traits
- , UniqueKeys
, typename packed_options::hash
, typename packed_options::equal
, typename packed_options::size_type
- , packed_options::constant_time_size
, real_bucket_traits
- , packed_options::power_2_buckets
- , packed_options::cache_begin
- , packed_options::compare_hash
+ , (std::size_t(UniqueKeys)*detail::hash_bool_flags::unique_keys_pos)
+ | (std::size_t(packed_options::constant_time_size)*detail::hash_bool_flags::constant_time_size_pos)
+ | (std::size_t(packed_options::power_2_buckets)*detail::hash_bool_flags::power_2_buckets_pos)
+ | (std::size_t(packed_options::cache_begin)*detail::hash_bool_flags::cache_begin_pos)
+ | (std::size_t(packed_options::compare_hash)*detail::hash_bool_flags::compare_hash_pos)
+ | (std::size_t(packed_options::incremental)*detail::hash_bool_flags::incremental_pos)
> type;
};
/// @endcond
//! Helper metafunction to define a \c hashtable that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
, class O5 = none, class O6 = none
, class O7 = none, class O8 = none
- , class O9 = none
+ , class O9 = none, class O10= none
>
#endif
struct make_hashtable
@@ -2630,20 +2917,42 @@
/// @cond
typedef hashtable_impl
< typename make_hashtable_opt
- <T, false, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
+ <T, false,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
-#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9>
+#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
+
+#if defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+template<class T, class ...Options>
+#else
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
+#endif
class hashtable
- : public make_hashtable<T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
-{
- typedef typename make_hashtable
- <T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type Base;
+ : public make_hashtable<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
+{
+ typedef typename make_hashtable<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_traits value_traits;
@@ -2669,7 +2978,6 @@
#endif
-
} //namespace intrusive
} //namespace boost
Modified: trunk/boost/intrusive/intrusive_fwd.hpp
==============================================================================
--- trunk/boost/intrusive/intrusive_fwd.hpp (original)
+++ trunk/boost/intrusive/intrusive_fwd.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -15,26 +15,12 @@
#include <cstddef>
#include <boost/intrusive/link_mode.hpp>
+#include <boost/intrusive/detail/workaround.hpp>
/// @cond
-//std predeclarations
-namespace std{
-
-template<class T>
-struct equal_to;
-
-template<class T>
-struct less;
-
-} //namespace std{
-
namespace boost {
-//Hash predeclaration
-template<class T>
-struct hash;
-
namespace intrusive {
struct none;
@@ -64,6 +50,7 @@
////////////////////////////
//slist
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -72,46 +59,70 @@
, class O4 = none
, class O5 = none
>
+#else
+template<class T, class ...Options>
+#endif
class slist;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class slist_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class slist_member_hook;
//list
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class T, class ...Options>
+#endif
class list;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class list_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class list_member_hook;
//rbtree/set/multiset
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -119,8 +130,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class rbtree;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -128,8 +143,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class set;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -137,25 +156,37 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class multiset;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class set_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class set_member_hook;
//splaytree/splay_set/splay_multiset
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -163,8 +194,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class splaytree;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -172,8 +207,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class splay_set;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -181,23 +220,35 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class splay_multiset;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class splay_set_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class splay_set_member_hook;
//avltree/avl_set/avl_multiset
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -205,8 +256,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class avltree;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -214,8 +269,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class avl_set;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -223,25 +282,37 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class avl_multiset;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class avl_set_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class avl_set_member_hook;
//sgtree/sg_set/sg_multiset
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -249,8 +320,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class sgtree;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -258,8 +333,12 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class sg_set;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -267,23 +346,36 @@
, class O3 = none
, class O4 = none
>
+#else
+template<class T, class ...Options>
+#endif
class sg_multiset;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class bs_set_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class bs_set_member_hook;
//hashtable/unordered_set/unordered_multiset
+
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -295,9 +387,14 @@
, class O7 = none
, class O8 = none
, class O9 = none
+ , class O10 = none
>
+#else
+template<class T, class ...Options>
+#endif
class hashtable;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -309,9 +406,14 @@
, class O7 = none
, class O8 = none
, class O9 = none
+ , class O10 = none
>
+#else
+template<class T, class ...Options>
+#endif
class unordered_set;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class T
, class O1 = none
@@ -323,37 +425,57 @@
, class O7 = none
, class O8 = none
, class O9 = none
+ , class O10 = none
>
+#else
+template<class T, class ...Options>
+#endif
class unordered_multiset;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class unordered_set_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
, class O4 = none
>
+#else
+template<class ...Options>
+#endif
class unordered_set_member_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class any_base_hook;
+#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES
template
< class O1 = none
, class O2 = none
, class O3 = none
>
+#else
+template<class ...Options>
+#endif
class any_member_hook;
} //namespace intrusive {
Modified: trunk/boost/intrusive/linear_slist_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/linear_slist_algorithms.hpp (original)
+++ trunk/boost/intrusive/linear_slist_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -58,7 +58,7 @@
typedef typename NodeTraits::const_node_ptr const_node_ptr;
typedef NodeTraits node_traits;
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an non-used list element, putting the next
//! pointer to null:
@@ -127,7 +127,7 @@
//! <b>Throws</b>: Nothing.
static void transfer_after(node_ptr p, node_ptr b, node_ptr e);
- #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #endif //#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: Constructs an empty list, making this_node the only
//! node of the circular list:
Modified: trunk/boost/intrusive/list.hpp
==============================================================================
--- trunk/boost/intrusive/list.hpp (original)
+++ trunk/boost/intrusive/list.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -35,20 +35,6 @@
/// @cond
-template <class T>
-struct internal_default_list_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_list_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_list_hook
-{
- typedef typename T::default_list_hook type;
-};
-
template <class ValueTraits, class SizeType, bool ConstantTimeSize>
struct listopt
{
@@ -57,17 +43,12 @@
static const bool constant_time_size = ConstantTimeSize;
};
+
template <class T>
struct list_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_list_hook<T>::value
- , get_default_list_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_list_hook>
, constant_time_size<true>
, size_type<std::size_t>
>::type
@@ -85,7 +66,7 @@
//! The container supports the following options:
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<> and \c size_type<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -225,7 +206,7 @@
{
this->priv_size_traits().set_size(size_type(0));
node_algorithms::init_header(this->get_root_node());
- this->insert(this->end(), b, e);
+ this->insert(this->cend(), b, e);
}
//! <b>Effects</b>: If it's not a safe-mode or an auto-unlink value_type
@@ -583,7 +564,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase(iterator i)
+ iterator erase(const_iterator i)
{ return this->erase_and_dispose(i, detail::null_disposer()); }
//! <b>Requires</b>: b and e must be valid iterators to elements in *this.
@@ -601,14 +582,14 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements.
- iterator erase(iterator b, iterator e)
+ iterator erase(const_iterator b, const_iterator e)
{
if(safemode_or_autounlink || constant_time_size){
return this->erase_and_dispose(b, e, detail::null_disposer());
}
else{
node_algorithms::unlink(b.pointed_node(), e.pointed_node());
- return e;
+ return e.unconst();
}
}
@@ -628,7 +609,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements.
- iterator erase(iterator b, iterator e, difference_type n)
+ iterator erase(const_iterator b, const_iterator e, difference_type n)
{
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(b, e) == difference_type(n));
if(safemode_or_autounlink || constant_time_size){
@@ -639,7 +620,7 @@
this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
}
node_algorithms::unlink(b.pointed_node(), e.pointed_node());
- return e;
+ return e.unconst();
}
}
@@ -658,7 +639,7 @@
//!
//! <b>Note</b>: Invalidates the iterators to the erased element.
template <class Disposer>
- iterator erase_and_dispose(iterator i, Disposer disposer)
+ iterator erase_and_dispose(const_iterator i, Disposer disposer)
{
node_ptr to_erase(i.pointed_node());
++i;
@@ -667,7 +648,7 @@
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
disposer(this->get_real_value_traits().to_value_ptr(to_erase));
- return i;
+ return i.unconst();
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -685,7 +666,7 @@
//!
//! <b>Note</b>: Invalidates the iterators to the erased elements.
template <class Disposer>
- iterator erase_and_dispose(iterator b, iterator e, Disposer disposer)
+ iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
{
node_ptr bp(b.pointed_node()), ep(e.pointed_node());
node_algorithms::unlink(bp, ep);
@@ -697,7 +678,7 @@
disposer(get_real_value_traits().to_value_ptr(to_erase));
this->priv_size_traits().decrement();
}
- return e;
+ return e.unconst();
}
//! <b>Effects</b>: Erases all the elements of the container.
@@ -734,7 +715,7 @@
template <class Disposer>
void clear_and_dispose(Disposer disposer)
{
- iterator it(this->begin()), itend(this->end());
+ const_iterator it(this->begin()), itend(this->end());
while(it != itend){
node_ptr to_erase(it.pointed_node());
++it;
@@ -747,6 +728,7 @@
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
@@ -783,7 +765,7 @@
//! <b>Complexity</b>: Constant time. No copy constructors are called.
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
- iterator insert(iterator p, reference value)
+ iterator insert(const_iterator p, reference value)
{
node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink)
@@ -805,7 +787,7 @@
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
template<class Iterator>
- void insert(iterator p, Iterator b, Iterator e)
+ void insert(const_iterator p, Iterator b, Iterator e)
{
for (; b != e; ++b)
this->insert(p, *b);
@@ -830,7 +812,7 @@
void assign(Iterator b, Iterator e)
{
this->clear();
- this->insert(this->end(), b, e);
+ this->insert(this->cend(), b, e);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -853,7 +835,7 @@
void dispose_and_assign(Disposer disposer, Iterator b, Iterator e)
{
this->clear_and_dispose(disposer);
- this->insert(this->end(), b, e);
+ this->insert(this->cend(), b, e);
}
//! <b>Requires</b>: p must be a valid iterator of *this.
@@ -867,7 +849,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, list_impl& x)
+ void splice(const_iterator p, list_impl& x)
{
if(!x.empty()){
size_traits &thist = this->priv_size_traits();
@@ -892,7 +874,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, list_impl&x, iterator new_ele)
+ void splice(const_iterator p, list_impl&x, const_iterator new_ele)
{
node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node());
x.priv_size_traits().decrement();
@@ -912,7 +894,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, list_impl&x, iterator start, iterator end)
+ void splice(const_iterator p, list_impl&x, const_iterator start, const_iterator end)
{
if(constant_time_size)
this->splice(p, x, start, end, std::distance(start, end));
@@ -933,7 +915,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator p, list_impl&x, iterator start, iterator end, difference_type n)
+ void splice(const_iterator p, list_impl&x, const_iterator start, const_iterator end, difference_type n)
{
if(n){
if(constant_time_size){
@@ -988,7 +970,7 @@
list_impl counter[64];
int fill = 0;
while(!this->empty()){
- carry.splice(carry.begin(), *this, this->begin());
+ carry.splice(carry.cbegin(), *this, this->cbegin());
int i = 0;
while(i < fill && !counter[i].empty()) {
carry.merge(counter[i++], p);
@@ -1034,13 +1016,13 @@
template<class Predicate>
void merge(list_impl& x, Predicate p)
{
- iterator e(this->end());
- iterator bx(x.begin());
- iterator ex(x.end());
+ const_iterator e(this->end());
+ const_iterator bx(x.begin());
+ const_iterator ex(x.end());
- for (iterator b = this->begin(); b != e; ++b) {
+ for (const_iterator b = this->cbegin(); b != e; ++b) {
size_type n(0);
- iterator ix(bx);
+ const_iterator ix(bx);
while(ix != ex && p(*ix, *b)){
++ix; ++n;
}
@@ -1116,8 +1098,8 @@
template<class Pred, class Disposer>
void remove_and_dispose_if(Pred pred, Disposer disposer)
{
- iterator cur(this->begin());
- iterator last(this->end());
+ const_iterator cur(this->cbegin());
+ const_iterator last(this->cend());
while(cur != last) {
if(pred(*cur)){
cur = this->erase_and_dispose(cur, disposer);
@@ -1185,11 +1167,11 @@
template<class BinaryPredicate, class Disposer>
void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{
- iterator itend(this->end());
- iterator cur(this->begin());
+ const_iterator itend(this->cend());
+ const_iterator cur(this->cbegin());
if(cur != itend){
- iterator after(cur);
+ const_iterator after(cur);
++after;
while(after != itend){
if(pred(*cur, *after)){
@@ -1284,26 +1266,26 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
@@ -1336,65 +1318,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
#else
(const list_impl<Config> &x, const list_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(list_impl<T, Options...> &x, list_impl<T, Options...> &y)
#else
(list_impl<Config> &x, list_impl<Config> &y)
@@ -1403,7 +1385,7 @@
//! Helper metafunction to define a \c list that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none, class O3 = none>
@@ -1412,7 +1394,14 @@
{
/// @cond
typedef typename pack_options
- < list_defaults<T>, O1, O2, O3>::type packed_options;
+ < list_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
@@ -1430,12 +1419,29 @@
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3>
+#else
+template<class T, class ...Options>
+#endif
class list
- : public make_list<T, O1, O2, O3>::type
+ : public make_list<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_list
- <T, O1, O2, O3>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type Base;
typedef typename Base::real_value_traits real_value_traits;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
Modified: trunk/boost/intrusive/list_hook.hpp
==============================================================================
--- trunk/boost/intrusive/list_hook.hpp (original)
+++ trunk/boost/intrusive/list_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -35,7 +35,7 @@
//! Helper metafunction to define a \c \c list_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -44,7 +44,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_list_node_algo<typename packed_options::void_pointer>
@@ -72,15 +78,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class list_base_hook
- : public make_list_base_hook<O1, O2, O3>::type
+ : public make_list_base_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -149,7 +161,7 @@
//! Helper metafunction to define a \c \c list_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -158,7 +170,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_list_node_algo<typename packed_options::void_pointer>
@@ -181,15 +199,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class list_member_hook
- : public make_list_member_hook<O1, O2, O3>::type
+ : public make_list_member_hook
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ <O1, O2, O3>
+ #else
+ <Options...>
+ #endif
+ ::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Modified: trunk/boost/intrusive/options.hpp
==============================================================================
--- trunk/boost/intrusive/options.hpp (original)
+++ trunk/boost/intrusive/options.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -31,6 +31,26 @@
namespace detail{
+struct default_hook_tag{};
+
+#define BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER) \
+struct BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER : public default_hook_tag\
+{\
+ template <class T>\
+ struct apply\
+ { typedef typename T::BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER type; };\
+}\
+
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_list_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_slist_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_set_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_uset_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_avl_set_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_splay_set_hook);
+BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION(default_bs_set_hook);
+
+#undef BOOST_INTRUSIVE_DEFAULT_HOOK_MARKER_DEFINITION
+
template <class ValueTraits>
struct eval_value_traits
{
@@ -116,8 +136,12 @@
template<class T, class SupposedValueTraits>
struct get_value_traits
{
- typedef SupposedValueTraits supposed_value_traits;
- //...if it's a base hook
+ typedef typename detail::eval_if_c
+ <detail::is_convertible<SupposedValueTraits*, detail::default_hook_tag*>::value
+ ,detail::apply<SupposedValueTraits, T>
+ ,detail::identity<SupposedValueTraits>
+ >::type supposed_value_traits;
+ //...if it's a default hook
typedef typename detail::eval_if_c
< internal_base_hook_bool_is_true<supposed_value_traits>::value
//...get it's internal value traits using
@@ -336,7 +360,7 @@
};
//!This option setter specifies the type of
-//!the tag of a base hook. A type can not have two
+//!the tag of a base hook. A type cannot have two
//!base hooks of the same type, so a tag can be used
//!to differentiate two base hooks with otherwise same type
template<class Tag>
@@ -509,8 +533,29 @@
/// @endcond
};
+//!This option setter specifies if the hash container will use incremental
+//!hashing. With incremental hashing the cost of hash table expansion is spread
+//!out across each hash table insertion operation, as opposed to be incurred all at once.
+//!Therefore linear hashing is well suited for interactive applications or real-time
+//!appplications where the worst-case insertion time of non-incremental hash containers
+//!(rehashing the whole bucket array) is not admisible.
+template<bool Enabled>
+struct incremental
+{
+ /// @cond
+ template<class Base>
+ struct pack : Base
+ {
+ static const bool incremental = Enabled;
+ };
+ /// @endcond
+};
+
/// @cond
+//To-do: pass to variadic templates
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+
template<class Prev, class Next>
struct do_pack
{
@@ -525,7 +570,6 @@
typedef Prev type;
};
-
template
< class DefaultOptions
, class O1 = none
@@ -537,7 +581,8 @@
, class O7 = none
, class O8 = none
, class O9 = none
- , class Option10 = none
+ , class O10 = none
+ , class O11 = none
>
struct pack_options
{
@@ -553,29 +598,164 @@
< typename do_pack
< typename do_pack
< typename do_pack
- < DefaultOptions
- , O1
+ < typename do_pack
+ < DefaultOptions
+ , O1
+ >::type
+ , O2
>::type
- , O2
+ , O3
>::type
- , O3
+ , O4
>::type
- , O4
+ , O5
>::type
- , O5
+ , O6
>::type
- , O6
+ , O7
>::type
- , O7
+ , O8
>::type
- , O8
+ , O9
>::type
- , O9
- >::type
- , Option10
+ , O10
+ >::type
+ , O11
>::type
type;
};
+#else
+
+//index_tuple
+template<int... Indexes>
+struct index_tuple{};
+
+//build_number_seq
+template<std::size_t Num, typename Tuple = index_tuple<> >
+struct build_number_seq;
+
+template<std::size_t Num, int... Indexes>
+struct build_number_seq<Num, index_tuple<Indexes...> >
+ : build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
+{};
+
+template<int... Indexes>
+struct build_number_seq<0, index_tuple<Indexes...> >
+{ typedef index_tuple<Indexes...> type; };
+
+template<class ...Types>
+struct typelist
+{};
+
+//invert_typelist
+template<class T>
+struct invert_typelist;
+
+template<int I, typename Tuple>
+struct typelist_element;
+
+template<int I, typename Head, typename... Tail>
+struct typelist_element<I, typelist<Head, Tail...> >
+{
+ typedef typename typelist_element<I-1, typelist<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct typelist_element<0, typelist<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+template<int ...Ints, class ...Types>
+typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>
+ inverted_typelist(index_tuple<Ints...>, typelist<Types...>)
+{
+ return typelist<typename typelist_element<(sizeof...(Types) - 1) - Ints, typelist<Types...> >::type...>();
+}
+
+//sizeof_typelist
+template<class Typelist>
+struct sizeof_typelist;
+
+template<class ...Types>
+struct sizeof_typelist< typelist<Types...> >
+{
+ static const std::size_t value = sizeof...(Types);
+};
+
+//invert_typelist_impl
+template<class Typelist, class Indexes>
+struct invert_typelist_impl;
+
+
+template<class Typelist, int ...Ints>
+struct invert_typelist_impl< Typelist, index_tuple<Ints...> >
+{
+ static const std::size_t last_idx = sizeof_typelist<Typelist>::value - 1;
+ typedef typelist
+ <typename typelist_element<last_idx - Ints, Typelist>::type...> type;
+};
+
+template<class Typelist, int Int>
+struct invert_typelist_impl< Typelist, index_tuple<Int> >
+{
+ typedef Typelist type;
+};
+
+template<class Typelist>
+struct invert_typelist_impl< Typelist, index_tuple<> >
+{
+ typedef Typelist type;
+};
+
+//invert_typelist
+template<class Typelist>
+struct invert_typelist;
+
+template<class ...Types>
+struct invert_typelist< typelist<Types...> >
+{
+ typedef typelist<Types...> typelist_t;
+ typedef typename build_number_seq<sizeof...(Types)>::type indexes_t;
+ typedef typename invert_typelist_impl<typelist_t, indexes_t>::type type;
+};
+
+//Do pack
+template<class Typelist>
+struct do_pack;
+
+template<>
+struct do_pack<typelist<> >;
+
+template<class Prev>
+struct do_pack<typelist<Prev> >
+{
+ typedef Prev type;
+};
+
+template<class Prev, class Last>
+struct do_pack<typelist<Prev, Last> >
+{
+ typedef typename Prev::template pack<Last> type;
+};
+
+template<class Prev, class ...Others>
+struct do_pack<typelist<Prev, Others...> >
+{
+ typedef typename Prev::template pack
+ <typename do_pack<typelist<Others...>>::type> type;
+};
+
+
+template<class ...Options>
+struct pack_options
+{
+ typedef typelist<Options...> typelist_t;
+ typedef typename invert_typelist<typelist_t>::type inverted_typelist;
+ typedef typename do_pack<inverted_typelist>::type type;
+};
+
+#endif
struct hook_defaults
: public pack_options
Modified: trunk/boost/intrusive/pointer_plus_bits.hpp
==============================================================================
--- trunk/boost/intrusive/pointer_plus_bits.hpp (original)
+++ trunk/boost/intrusive/pointer_plus_bits.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -14,6 +14,7 @@
#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP
#include <boost/intrusive/detail/mpl.hpp> //ls_zeros
+#include <boost/intrusive/detail/assert.hpp> //BOOST_INTRUSIVE_INVARIANT_ASSERT
namespace boost {
namespace intrusive {
@@ -28,7 +29,7 @@
static const std::size_t value = 0;
};
-//!This is an specialization for raw pointers.
+//!This is a specialization for raw pointers.
//!Raw pointers can embed extra bits in the lower bits
//!if the alignment is multiple of 2pow(NumBits).
template<std::size_t Alignment>
@@ -61,7 +62,7 @@
static void set_pointer(pointer &n, pointer p)
{
- assert(0 == (std::size_t(p) & Mask));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(0 == (std::size_t(p) & Mask));
n = pointer(std::size_t(p) | (std::size_t(n) & Mask));
}
@@ -70,7 +71,7 @@
static void set_bits(pointer &n, std::size_t c)
{
- assert(c <= Mask);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(c <= Mask);
n = pointer(std::size_t(get_pointer(n)) | c);
}
};
Modified: trunk/boost/intrusive/rbtree.hpp
==============================================================================
--- trunk/boost/intrusive/rbtree.hpp (original)
+++ trunk/boost/intrusive/rbtree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -36,20 +36,6 @@
/// @cond
-template <class T>
-struct internal_default_set_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_set_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_set_hook
-{
- typedef typename T::default_set_hook type;
-};
-
template <class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize>
struct setopt
{
@@ -63,13 +49,7 @@
struct set_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_set_hook<T>::value
- , get_default_set_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_set_hook>
, constant_time_size<true>
, size_type<std::size_t>
, compare<std::less<T> >
@@ -91,7 +71,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1055,29 +1035,34 @@
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer)
{
this->clear_and_dispose(disposer);
if(!src.empty()){
+ detail::exception_disposer<rbtree_impl, Disposer>
+ rollback(*this, disposer);
node_algorithms::clone
(const_node_ptr(&src.priv_header())
,node_ptr(&this->priv_header())
,detail::node_cloner<Cloner, rbtree_impl>(cloner, this)
,detail::node_disposer<Disposer, rbtree_impl>(disposer, this));
this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ this->priv_comp() = src.priv_comp();
+ rollback.release();
}
}
@@ -1253,26 +1238,26 @@
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
@@ -1304,65 +1289,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const rbtree_impl<T, Options...> &x, const rbtree_impl<T, Options...> &y)
#else
(const rbtree_impl<Config> &x, const rbtree_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(rbtree_impl<T, Options...> &x, rbtree_impl<T, Options...> &y)
#else
(rbtree_impl<Config> &x, rbtree_impl<Config> &y)
@@ -1370,15 +1355,23 @@
{ x.swap(y); }
/// @cond
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
- , class O5 = none, class O6 = none
- , class O7 = none
>
+#else
+template<class T, class ...Options>
+#endif
struct make_rbtree_opt
{
typedef typename pack_options
- < set_defaults<T>, O1, O2, O3, O4>::type packed_options;
+ < set_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
@@ -1393,7 +1386,7 @@
//! Helper metafunction to define a \c rbtree that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1403,19 +1396,42 @@
{
/// @cond
typedef rbtree_impl
- < typename make_rbtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_rbtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class rbtree
- : public make_rbtree<T, O1, O2, O3, O4>::type
+ : public make_rbtree<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_rbtree
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/set.hpp
==============================================================================
--- trunk/boost/intrusive/set.hpp (original)
+++ trunk/boost/intrusive/set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -32,7 +32,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -324,18 +324,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const set_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -997,65 +998,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const set_impl<T, Options...> &x, const set_impl<T, Options...> &y)
#else
(const set_impl<Config> &x, const set_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const set_impl<T, Options...> &x, const set_impl<T, Options...> &y)
#else
(const set_impl<Config> &x, const set_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const set_impl<T, Options...> &x, const set_impl<T, Options...> &y)
#else
(const set_impl<Config> &x, const set_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const set_impl<T, Options...> &x, const set_impl<T, Options...> &y)
#else
(const set_impl<Config> &x, const set_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(set_impl<T, Options...> &x, set_impl<T, Options...> &y)
#else
(set_impl<Config> &x, set_impl<Config> &y)
@@ -1064,7 +1065,7 @@
//! Helper metafunction to define a \c set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1074,19 +1075,41 @@
{
/// @cond
typedef set_impl
- < typename make_rbtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_rbtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class set
- : public make_set<T, O1, O2, O3, O4>::type
+ : public make_set<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_set
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
@@ -1135,7 +1158,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1423,18 +1446,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -2018,65 +2042,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const multiset_impl<T, Options...> &x, const multiset_impl<T, Options...> &y)
#else
(const multiset_impl<Config> &x, const multiset_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const multiset_impl<T, Options...> &x, const multiset_impl<T, Options...> &y)
#else
(const multiset_impl<Config> &x, const multiset_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const multiset_impl<T, Options...> &x, const multiset_impl<T, Options...> &y)
#else
(const multiset_impl<Config> &x, const multiset_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const multiset_impl<T, Options...> &x, const multiset_impl<T, Options...> &y)
#else
(const multiset_impl<Config> &x, const multiset_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(multiset_impl<T, Options...> &x, multiset_impl<T, Options...> &y)
#else
(multiset_impl<Config> &x, multiset_impl<Config> &y)
@@ -2085,7 +2109,7 @@
//! Helper metafunction to define a \c multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -2095,19 +2119,41 @@
{
/// @cond
typedef multiset_impl
- < typename make_rbtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_rbtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class multiset
- : public make_multiset<T, O1, O2, O3, O4>::type
+ : public make_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
- typedef typename make_multiset
- <T, O1, O2, O3, O4>::type Base;
+ typedef typename make_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/set_hook.hpp (original)
+++ trunk/boost/intrusive/set_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -35,7 +35,7 @@
//! Helper metafunction to define a \c set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -44,7 +44,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_set_node_algo<typename packed_options::void_pointer
@@ -77,15 +83,21 @@
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class set_base_hook
- : public make_set_base_hook<O1, O2, O3, O4>::type
+ : public make_set_base_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -154,7 +166,7 @@
//! Helper metafunction to define a \c set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -163,7 +175,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_set_node_algo<typename packed_options::void_pointer
@@ -191,15 +209,21 @@
//!
//! \c optimize_size<> will tell the hook to optimize the hook for size instead
//! of speed.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class set_member_hook
- : public make_set_member_hook<O1, O2, O3, O4>::type
+ : public make_set_member_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Modified: trunk/boost/intrusive/sg_set.hpp
==============================================================================
--- trunk/boost/intrusive/sg_set.hpp (original)
+++ trunk/boost/intrusive/sg_set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -31,7 +31,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -323,18 +323,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -1035,65 +1036,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_set_impl<T, Options...> &x, const sg_set_impl<T, Options...> &y)
#else
(const sg_set_impl<Config> &x, const sg_set_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_set_impl<T, Options...> &x, const sg_set_impl<T, Options...> &y)
#else
(const sg_set_impl<Config> &x, const sg_set_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_set_impl<T, Options...> &x, const sg_set_impl<T, Options...> &y)
#else
(const sg_set_impl<Config> &x, const sg_set_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_set_impl<T, Options...> &x, const sg_set_impl<T, Options...> &y)
#else
(const sg_set_impl<Config> &x, const sg_set_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(sg_set_impl<T, Options...> &x, sg_set_impl<T, Options...> &y)
#else
(sg_set_impl<Config> &x, sg_set_impl<Config> &y)
@@ -1102,7 +1103,7 @@
//! Helper metafunction to define a \c sg_set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1112,19 +1113,42 @@
{
/// @cond
typedef sg_set_impl
- < typename make_sgtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_sgtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class sg_set
- : public make_sg_set<T, O1, O2, O3, O4>::type
+ : public make_sg_set<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_sg_set
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
@@ -1173,7 +1197,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1461,18 +1485,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -2080,65 +2105,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_multiset_impl<T, Options...> &x, const sg_multiset_impl<T, Options...> &y)
#else
(const sg_multiset_impl<Config> &x, const sg_multiset_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_multiset_impl<T, Options...> &x, const sg_multiset_impl<T, Options...> &y)
#else
(const sg_multiset_impl<Config> &x, const sg_multiset_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_multiset_impl<T, Options...> &x, const sg_multiset_impl<T, Options...> &y)
#else
(const sg_multiset_impl<Config> &x, const sg_multiset_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sg_multiset_impl<T, Options...> &x, const sg_multiset_impl<T, Options...> &y)
#else
(const sg_multiset_impl<Config> &x, const sg_multiset_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(sg_multiset_impl<T, Options...> &x, sg_multiset_impl<T, Options...> &y)
#else
(sg_multiset_impl<Config> &x, sg_multiset_impl<Config> &y)
@@ -2147,7 +2172,7 @@
//! Helper metafunction to define a \c sg_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -2157,19 +2182,42 @@
{
/// @cond
typedef sg_multiset_impl
- < typename make_sgtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_sgtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class sg_multiset
- : public make_sg_multiset<T, O1, O2, O3, O4>::type
+ : public make_sg_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_sg_multiset
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/sgtree.hpp
==============================================================================
--- trunk/boost/intrusive/sgtree.hpp (original)
+++ trunk/boost/intrusive/sgtree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -151,7 +151,7 @@
void set_alpha(float)
{ //alpha CAN't be changed.
- assert(0);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
}
h_alpha_t get_h_alpha_t() const
@@ -176,13 +176,7 @@
struct sg_set_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_bs_set_hook<T>::value
- , get_default_bs_set_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_bs_set_hook>
, floating_point<true>
, size_type<std::size_t>
, compare<std::less<T> >
@@ -204,7 +198,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c floating_point<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1212,29 +1206,34 @@
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer)
{
this->clear_and_dispose(disposer);
if(!src.empty()){
+ detail::exception_disposer<sgtree_impl, Disposer>
+ rollback(*this, disposer);
node_algorithms::clone
(const_node_ptr(&src.priv_header())
,node_ptr(&this->priv_header())
,detail::node_cloner<Cloner, sgtree_impl>(cloner, this)
,detail::node_disposer<Disposer, sgtree_impl>(disposer, this));
this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ this->priv_comp() = src.priv_comp();
+ rollback.release();
}
}
@@ -1469,26 +1468,26 @@
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
@@ -1520,65 +1519,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const sgtree_impl<T, Options...> &x, const sgtree_impl<T, Options...> &y)
#else
(const sgtree_impl<Config> &x, const sgtree_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(sgtree_impl<T, Options...> &x, sgtree_impl<T, Options...> &y)
#else
(sgtree_impl<Config> &x, sgtree_impl<Config> &y)
@@ -1586,15 +1585,22 @@
{ x.swap(y); }
/// @cond
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1 = none, class O2 = none
- , class O3 = none, class O4 = none
- , class O5 = none, class O6 = none
- , class O7 = none
- >
+ , class O3 = none, class O4 = none>
+#else
+template<class T, class ...Options>
+#endif
struct make_sgtree_opt
{
typedef typename pack_options
- < sg_set_defaults<T>, O1, O2, O3, O4>::type packed_options;
+ < sg_set_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
@@ -1609,7 +1615,7 @@
//! Helper metafunction to define a \c sgtree that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1619,19 +1625,41 @@
{
/// @cond
typedef sgtree_impl
- < typename make_sgtree_opt<T, O1, O2, O3, O4>::type
+ < typename make_sgtree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class sgtree
- : public make_sgtree<T, O1, O2, O3, O4>::type
+ : public make_sgtree<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_sgtree
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/sgtree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/sgtree_algorithms.hpp (original)
+++ trunk/boost/intrusive/sgtree_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -683,7 +683,7 @@
for(std::size_t i = 1; true; ++i){
bool rebalance = false;
if(i == depth){
- assert(tree_size == count(s));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(tree_size == count(s));
rebalance = true;
}
else if(i > h_alpha(size)){
Modified: trunk/boost/intrusive/slist.hpp
==============================================================================
--- trunk/boost/intrusive/slist.hpp (original)
+++ trunk/boost/intrusive/slist.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -36,18 +36,6 @@
/// @cond
-template <class T>
-struct internal_default_slist_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_slist_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_slist_hook
-{ typedef typename T::default_slist_hook type; };
-
template <class ValueTraits, class SizeType, bool ConstantTimeSize, bool Linear, bool CacheLast>
struct slistopt
{
@@ -75,13 +63,7 @@
struct slist_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_slist_hook<T>::value
- , get_default_slist_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_slist_hook>
, constant_time_size<true>
, linear<false>
, size_type<std::size_t>
@@ -114,7 +96,7 @@
//! the '*_after' functions, ++end() == begin() and previous(begin()) == end()
//! are defined. An new special function "before_begin()" is defined, which returns
//! an iterator that points one less the beginning of the list: ++before_begin() == begin()
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -300,7 +282,7 @@
: data_(v_traits)
{
this->set_default_constructed_state();
- this->insert_after(this->before_begin(), b, e);
+ this->insert_after(this->cbefore_begin(), b, e);
}
//! <b>Effects</b>: If it's a safe-mode
@@ -346,7 +328,7 @@
template <class Disposer>
void clear_and_dispose(Disposer disposer)
{
- iterator it(this->begin()), itend(this->end());
+ const_iterator it(this->begin()), itend(this->end());
while(it != itend){
node_ptr to_erase(it.pointed_node());
++it;
@@ -395,7 +377,7 @@
void push_back(reference value)
{
BOOST_STATIC_ASSERT((cache_last != 0));
- this->insert_after(iterator(this->get_last_node(), this), value);
+ this->insert_after(const_iterator(this->get_last_node(), this), value);
}
//! <b>Effects</b>: Erases the first element of the list.
@@ -650,6 +632,7 @@
{ this->priv_shift_forward(n, detail::bool_<linear>()); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
@@ -668,7 +651,7 @@
this->clear_and_dispose(disposer);
detail::exception_disposer<slist_impl, Disposer>
rollback(*this, disposer);
- iterator prev(this->before_begin());
+ const_iterator prev(this->cbefore_begin());
const_iterator b(src.begin()), e(src.end());
for(; b != e; ++b){
prev = this->insert_after(prev, *cloner(*b));
@@ -689,7 +672,7 @@
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
- iterator insert_after(iterator prev_p, reference value)
+ iterator insert_after(const_iterator prev_p, reference value)
{
node_ptr n = get_real_value_traits().to_node_ptr(value);
if(safemode_or_autounlink)
@@ -716,7 +699,7 @@
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
template<class Iterator>
- void insert_after(iterator prev_p, Iterator first, Iterator last)
+ void insert_after(const_iterator prev_p, Iterator first, Iterator last)
{
for (; first != last; ++first)
prev_p = this->insert_after(prev_p, *first);
@@ -734,7 +717,7 @@
//! Constant-time if cache_last<> is true and p == end().
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
- iterator insert(iterator p, reference value)
+ iterator insert(const_iterator p, reference value)
{ return this->insert_after(this->previous(p), value); }
//! <b>Requires</b>: Dereferencing iterator must yield
@@ -752,7 +735,7 @@
//!
//! <b>Note</b>: Does not affect the validity of iterators and references.
template<class Iterator>
- void insert(iterator p, Iterator b, Iterator e)
+ void insert(const_iterator p, Iterator b, Iterator e)
{ return this->insert_after(this->previous(p), b, e); }
//! <b>Effects</b>: Erases the element after the element pointed by prev of
@@ -767,7 +750,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase_after(iterator prev)
+ iterator erase_after(const_iterator prev)
{ return this->erase_after_and_dispose(prev, detail::null_disposer()); }
//! <b>Effects</b>: Erases the range (before_first, last) from
@@ -783,7 +766,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase_after(iterator before_first, iterator last)
+ iterator erase_after(const_iterator before_first, const_iterator last)
{
if(safemode_or_autounlink || constant_time_size){
return this->erase_after_and_dispose(before_first, last, detail::null_disposer());
@@ -797,7 +780,7 @@
}
}
node_algorithms::unlink_after(bfp, lp);
- return last;
+ return last.unconst();
}
}
@@ -815,9 +798,9 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase_after(iterator before_first, iterator last, difference_type n)
+ iterator erase_after(const_iterator before_first, const_iterator last, difference_type n)
{
- BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++iterator(before_first), last) == difference_type(n));
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++const_iterator(before_first), last) == difference_type(n));
if(safemode_or_autounlink){
return this->erase_after(before_first, last);
}
@@ -833,7 +816,7 @@
if(constant_time_size){
this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n);
}
- return last;
+ return last.unconst();
}
}
@@ -849,7 +832,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase(iterator i)
+ iterator erase(const_iterator i)
{ return this->erase_after(this->previous(i)); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -866,7 +849,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements.
- iterator erase(iterator first, iterator last)
+ iterator erase(const_iterator first, const_iterator last)
{ return this->erase_after(this->previous(first), last); }
//! <b>Effects</b>: Erases the range [first, last) from
@@ -883,7 +866,7 @@
//!
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
- iterator erase(iterator first, iterator last, difference_type n)
+ iterator erase(const_iterator first, const_iterator last, difference_type n)
{ return this->erase_after(this->previous(first), last, n); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -901,9 +884,9 @@
//!
//! <b>Note</b>: Invalidates the iterators to the erased element.
template<class Disposer>
- iterator erase_after_and_dispose(iterator prev, Disposer disposer)
+ iterator erase_after_and_dispose(const_iterator prev, Disposer disposer)
{
- iterator it(prev);
+ const_iterator it(prev);
++it;
node_ptr to_erase(it.pointed_node());
++it;
@@ -916,16 +899,16 @@
node_algorithms::init(to_erase);
disposer(get_real_value_traits().to_value_ptr(to_erase));
this->priv_size_traits().decrement();
- return it;
+ return it.unconst();
}
/// @cond
template<class Disposer>
- static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer)
+ static iterator s_erase_after_and_dispose(const_iterator prev, Disposer disposer)
{
BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits)));
- iterator it(prev);
+ const_iterator it(prev);
++it;
node_ptr to_erase(it.pointed_node());
++it;
@@ -934,10 +917,10 @@
if(safemode_or_autounlink)
node_algorithms::init(to_erase);
disposer(real_value_traits::to_value_ptr(to_erase));
- return it;
+ return it.unconst();
}
- static iterator s_erase_after(iterator prev)
+ static iterator s_erase_after(const_iterator prev)
{ return s_erase_after_and_dispose(prev, detail::null_disposer()); }
/// @endcond
@@ -957,7 +940,7 @@
//!
//! <b>Note</b>: Invalidates the iterators to the erased element.
template<class Disposer>
- iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer)
+ iterator erase_after_and_dispose(const_iterator before_first, const_iterator last, Disposer disposer)
{
node_ptr bfp(before_first.pointed_node()), lp(last.pointed_node());
node_ptr fp(node_traits::get_next(bfp));
@@ -973,7 +956,7 @@
if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){
this->set_last_node(bfp);
}
- return last;
+ return last.unconst();
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -992,7 +975,7 @@
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased element.
template<class Disposer>
- iterator erase_and_dispose(iterator i, Disposer disposer)
+ iterator erase_and_dispose(const_iterator i, Disposer disposer)
{ return this->erase_after_and_dispose(this->previous(i), disposer); }
//! <b>Requires</b>: first and last must be valid iterator to elements in *this.
@@ -1013,7 +996,7 @@
//! <b>Note</b>: Invalidates the iterators (but not the references) to the
//! erased elements.
template<class Disposer>
- iterator erase_and_dispose(iterator first, iterator last, Disposer disposer)
+ iterator erase_and_dispose(const_iterator first, const_iterator last, Disposer disposer)
{ return this->erase_after_and_dispose(this->previous(first), last, disposer); }
//! <b>Requires</b>: Dereferencing iterator must yield
@@ -1035,7 +1018,7 @@
void assign(Iterator b, Iterator e)
{
this->clear();
- this->insert_after(this->before_begin(), b, e);
+ this->insert_after(this->cbefore_begin(), b, e);
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
@@ -1058,7 +1041,7 @@
void dispose_and_assign(Disposer disposer, Iterator b, Iterator e)
{
this->clear_and_dispose(disposer);
- this->insert_after(this->before_begin(), b, e, disposer);
+ this->insert_after(this->cbefore_begin(), b, e, disposer);
}
//! <b>Requires</b>: prev is an iterator to an element or x.end()/x.before_begin() in x.
@@ -1077,10 +1060,10 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- iterator splice_after(iterator prev, slist_impl &x)
+ iterator splice_after(const_iterator prev, slist_impl &x)
{
if (!x.empty()){
- iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
+ const_iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
node_ptr prev_n(prev.pointed_node());
node_ptr last_x_n(last_x.pointed_node());
if(cache_last){
@@ -1092,10 +1075,10 @@
node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n);
this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size());
x.priv_size_traits().set_size(size_type(0));
- return last_x;
+ return last_x.unconst();
}
else{
- return prev;
+ return prev.unconst();
}
}
@@ -1112,9 +1095,9 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele)
+ void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator prev_ele)
{
- iterator elem = prev_ele;
+ const_iterator elem = prev_ele;
this->splice_after(prev_pos, x, prev_ele, ++elem, 1);
}
@@ -1133,7 +1116,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last)
+ void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_first, const_iterator before_last)
{
if(constant_time_size)
this->splice_after(prev_pos, x, before_first, before_last, std::distance(before_first, before_last));
@@ -1156,7 +1139,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n)
+ void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_first, const_iterator before_last, difference_type n)
{
if(n){
BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n);
@@ -1188,7 +1171,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- iterator splice(iterator it, slist_impl &x)
+ iterator splice(const_iterator it, slist_impl &x)
{ return this->splice_after(this->previous(it), x); }
//! <b>Requires</b>: it p must be a valid iterator of *this.
@@ -1205,7 +1188,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator pos, slist_impl &x, iterator elem)
+ void splice(const_iterator pos, slist_impl &x, const_iterator elem)
{ return this->splice_after(this->previous(pos), x, x.previous(elem)); }
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this
@@ -1225,7 +1208,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator pos, slist_impl &x, iterator first, iterator last)
+ void splice(const_iterator pos, slist_impl &x, const_iterator first, const_iterator last)
{ return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last)); }
//! <b>Requires</b>: pos must be a dereferenceable iterator in *this
@@ -1244,7 +1227,7 @@
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
//! list. Iterators of this list and all the references are not invalidated.
- void splice(iterator pos, slist_impl &x, iterator first, iterator last, difference_type n)
+ void splice(const_iterator pos, slist_impl &x, const_iterator first, const_iterator last, difference_type n)
{ return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last), n); }
//! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
@@ -1266,10 +1249,10 @@
slist_impl carry;
slist_impl counter[64];
int fill = 0;
- iterator last_inserted;
+ const_iterator last_inserted;
while(!this->empty()){
- last_inserted = this->begin();
- carry.splice_after(carry.before_begin(), *this, this->before_begin());
+ last_inserted = this->cbegin();
+ carry.splice_after(carry.cbefore_begin(), *this, this->cbefore_begin());
int i = 0;
while(i < fill && !counter[i].empty()) {
last_inserted = carry.merge(counter[i++], p);
@@ -1277,16 +1260,16 @@
BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty());
node_ptr p = node_algorithms::get_previous_node
- (last_inserted.pointed_node(), carry.end().pointed_node());
- iterator last_element(p, this);
+ (last_inserted.pointed_node(), carry.cend().pointed_node());
+ const_iterator last_element(p, this);
if(constant_time_size){
- counter[i].splice_after( counter[i].before_begin(), carry
- , carry.before_begin(), last_element
+ counter[i].splice_after( counter[i].cbefore_begin(), carry
+ , carry.cbefore_begin(), last_element
, carry.size());
}
else{
- counter[i].splice_after( counter[i].before_begin(), carry
- , carry.before_begin(), last_element);
+ counter[i].splice_after( counter[i].cbefore_begin(), carry
+ , carry.cbefore_begin(), last_element);
}
if(i == fill)
++fill;
@@ -1298,13 +1281,13 @@
node_ptr p = node_algorithms::get_previous_node
(last_inserted.pointed_node(), counter[--fill].end().pointed_node());
- iterator last_element(p, this);
+ const_iterator last_element(p, this);
if(constant_time_size){
- this->splice_after( before_begin(), counter[fill], counter[fill].before_begin()
+ this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin()
, last_element, counter[fill].size());
}
else{
- this->splice_after( before_begin(), counter[fill], counter[fill].before_begin()
+ this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin()
, last_element);
}
}
@@ -1348,12 +1331,12 @@
template<class Predicate>
iterator merge(slist_impl& x, Predicate p)
{
- iterator a(before_begin()), e(end()), ax(x.before_begin()), ex(x.end());
- iterator last_inserted(e);
- iterator a_next;
+ const_iterator a(cbefore_begin()), e(cend()), ax(x.cbefore_begin()), ex(x.cend());
+ const_iterator last_inserted(e);
+ const_iterator a_next;
while(++(a_next = a) != e && !x.empty()) {
- iterator ix(ax);
- iterator cx;
+ const_iterator ix(ax);
+ const_iterator cx;
size_type n(0);
while(++(cx = ix) != ex && p(*cx, *a_next)){
++ix; ++n;
@@ -1367,7 +1350,7 @@
if (!x.empty()){
last_inserted = this->splice_after(a, x);
}
- return last_inserted;
+ return last_inserted.unconst();
}
//! <b>Effects</b>: This function removes all of x's elements and inserts them
@@ -1455,7 +1438,7 @@
template<class Pred, class Disposer>
void remove_and_dispose_if(Pred pred, Disposer disposer)
{
- iterator bcur(this->before_begin()), cur(this->begin()), e(this->end());
+ const_iterator bcur(this->before_begin()), cur(this->begin()), e(this->end());
while(cur != e){
if (pred(*cur)){
@@ -1528,10 +1511,10 @@
template<class BinaryPredicate, class Disposer>
void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
{
- iterator end_n(this->end());
- iterator bcur(this->begin());
+ const_iterator end_n(this->cend());
+ const_iterator bcur(this->cbegin());
if(bcur != end_n){
- iterator cur(bcur);
+ const_iterator cur(bcur);
++cur;
while(cur != end_n) {
if (pred(*bcur, *cur)){
@@ -1643,7 +1626,7 @@
const_iterator previous(const_iterator i) const
{
if(cache_last && (i.pointed_node() == this->get_end_node())){
- return iterator(uncast(this->get_last_node()), this);
+ return const_iterator(uncast(this->get_last_node()), this);
}
return const_iterator
(node_algorithms::get_previous_node
@@ -1760,26 +1743,26 @@
}
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
@@ -1812,65 +1795,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
#else
(const slist_impl<Config> &x, const slist_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(slist_impl<T, Options...> &x, slist_impl<T, Options...> &y)
#else
(slist_impl<Config> &x, slist_impl<Config> &y)
@@ -1879,7 +1862,7 @@
//! Helper metafunction to define a \c slist that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none, class O3 = none, class O4 = none, class O5 = none>
@@ -1888,7 +1871,13 @@
{
/// @cond
typedef typename pack_options
- < slist_defaults<T>, O1, O2, O3, O4, O5>::type packed_options;
+ < slist_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
typedef slist_impl
@@ -1907,12 +1896,29 @@
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4, class O5>
+#else
+template<class T, class ...Options>
+#endif
class slist
- : public make_slist<T, O1, O2, O3, O4, O5>::type
+ : public make_slist<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_slist
- <T, O1, O2, O3, O4, O5>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5
+ #else
+ Options...
+ #endif
+ >::type Base;
typedef typename Base::real_value_traits real_value_traits;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
Modified: trunk/boost/intrusive/slist_hook.hpp
==============================================================================
--- trunk/boost/intrusive/slist_hook.hpp (original)
+++ trunk/boost/intrusive/slist_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -37,7 +37,7 @@
//! Helper metafunction to define a \c slist_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -46,7 +46,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_slist_node_algo<typename packed_options::void_pointer>
@@ -75,15 +81,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class slist_base_hook
- : public make_slist_base_hook<O1, O2, O3>::type
+ : public make_slist_base_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -152,7 +164,7 @@
//! Helper metafunction to define a \c slist_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -161,7 +173,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_slist_node_algo<typename packed_options::void_pointer>
@@ -185,15 +203,21 @@
//!
//! \c void_pointer<> is the pointer type that will be used internally in the hook
//! and the the container configured to use this hook.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class slist_member_hook
- : public make_slist_member_hook<O1, O2, O3>::type
+ : public make_slist_member_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Modified: trunk/boost/intrusive/splay_set.hpp
==============================================================================
--- trunk/boost/intrusive/splay_set.hpp (original)
+++ trunk/boost/intrusive/splay_set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -31,7 +31,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -323,18 +323,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -1072,65 +1073,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_set_impl<T, Options...> &x, const splay_set_impl<T, Options...> &y)
#else
(const splay_set_impl<Config> &x, const splay_set_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_set_impl<T, Options...> &x, const splay_set_impl<T, Options...> &y)
#else
(const splay_set_impl<Config> &x, const splay_set_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_set_impl<T, Options...> &x, const splay_set_impl<T, Options...> &y)
#else
(const splay_set_impl<Config> &x, const splay_set_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_set_impl<T, Options...> &x, const splay_set_impl<T, Options...> &y)
#else
(const splay_set_impl<Config> &x, const splay_set_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(splay_set_impl<T, Options...> &x, splay_set_impl<T, Options...> &y)
#else
(splay_set_impl<Config> &x, splay_set_impl<Config> &y)
@@ -1139,7 +1140,7 @@
//! Helper metafunction to define a \c splay_set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1149,19 +1150,41 @@
{
/// @cond
typedef splay_set_impl
- < typename make_splaytree_opt<T, O1, O2, O3, O4>::type
+ < typename make_splaytree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class splay_set
- : public make_splay_set<T, O1, O2, O3, O4>::type
+ : public make_splay_set<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_splay_set
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
@@ -1210,7 +1233,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1498,18 +1521,19 @@
{ tree_.swap(other.tree_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer)
{ tree_.clone_from(src.tree_, cloner, disposer); }
@@ -2154,65 +2178,65 @@
/// @endcond
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_multiset_impl<T, Options...> &x, const splay_multiset_impl<T, Options...> &y)
#else
(const splay_multiset_impl<Config> &x, const splay_multiset_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_multiset_impl<T, Options...> &x, const splay_multiset_impl<T, Options...> &y)
#else
(const splay_multiset_impl<Config> &x, const splay_multiset_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_multiset_impl<T, Options...> &x, const splay_multiset_impl<T, Options...> &y)
#else
(const splay_multiset_impl<Config> &x, const splay_multiset_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splay_multiset_impl<T, Options...> &x, const splay_multiset_impl<T, Options...> &y)
#else
(const splay_multiset_impl<Config> &x, const splay_multiset_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(splay_multiset_impl<T, Options...> &x, splay_multiset_impl<T, Options...> &y)
#else
(splay_multiset_impl<Config> &x, splay_multiset_impl<Config> &y)
@@ -2221,7 +2245,7 @@
//! Helper metafunction to define a \c splay_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -2231,19 +2255,42 @@
{
/// @cond
typedef splay_multiset_impl
- < typename make_splaytree_opt<T, O1, O2, O3, O4>::type
+ < typename make_splaytree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class splay_multiset
- : public make_splay_multiset<T, O1, O2, O3, O4>::type
+ : public make_splay_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_splay_multiset
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/splay_set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/splay_set_hook.hpp (original)
+++ trunk/boost/intrusive/splay_set_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -34,7 +34,7 @@
//! Helper metafunction to define a \c splay_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -43,7 +43,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_splay_set_node_algo<typename packed_options::void_pointer>
@@ -72,15 +78,21 @@
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class splay_set_base_hook
- : public make_splay_set_base_hook<O1, O2, O3>::type
+ : public make_splay_set_base_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -149,7 +161,7 @@
//! Helper metafunction to define a \c splay_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none>
@@ -158,7 +170,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_splay_set_node_algo<typename packed_options::void_pointer>
@@ -183,15 +201,21 @@
//!
//! \c link_mode<> will specify the linking mode of the hook (\c normal_link,
//! \c auto_unlink or \c safe_link).
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3>
#endif
class splay_set_member_hook
- : public make_splay_set_member_hook<O1, O2, O3>::type
+ : public make_splay_set_member_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Modified: trunk/boost/intrusive/splaytree.hpp
==============================================================================
--- trunk/boost/intrusive/splaytree.hpp (original)
+++ trunk/boost/intrusive/splaytree.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -35,20 +35,6 @@
/// @cond
-template <class T>
-struct internal_default_splay_set_hook
-{
- template <class U> static detail::one test(...);
- template <class U> static detail::two test(typename U::default_splay_set_hook* = 0);
- static const bool value = sizeof(test<T>(0)) == sizeof(detail::two);
-};
-
-template <class T>
-struct get_default_splay_set_hook
-{
- typedef typename T::default_splay_set_hook type;
-};
-
template <class ValueTraits, class Compare, class SizeType, bool ConstantTimeSize>
struct splaysetopt
{
@@ -62,13 +48,7 @@
struct splay_set_defaults
: pack_options
< none
- , base_hook
- < typename detail::eval_if_c
- < internal_default_splay_set_hook<T>::value
- , get_default_splay_set_hook<T>
- , detail::identity<none>
- >::type
- >
+ , base_hook<detail::default_splay_set_hook>
, constant_time_size<true>
, size_type<std::size_t>
, compare<std::less<T> >
@@ -90,7 +70,7 @@
//! \c base_hook<>/member_hook<>/value_traits<>,
//! \c constant_time_size<>, \c size_type<> and
//! \c compare<>.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1072,29 +1052,34 @@
}
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes equivalent to the original nodes.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. Copies the predicate from the source container.
//!
//! If cloner throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner throws or predicate copy assignment throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer)
{
this->clear_and_dispose(disposer);
if(!src.empty()){
+ detail::exception_disposer<splaytree_impl, Disposer>
+ rollback(*this, disposer);
node_algorithms::clone
(const_node_ptr(&src.priv_header())
,node_ptr(&this->priv_header())
,detail::node_cloner<Cloner, splaytree_impl>(cloner, this)
,detail::node_disposer<Disposer, splaytree_impl>(disposer, this));
this->priv_size_traits().set_size(src.priv_size_traits().get_size());
+ this->priv_comp() = src.priv_comp();
+ rollback.release();
}
}
@@ -1339,26 +1324,26 @@
{ return priv_container_from_end_iterator(it.end_iterator_from_it()); }
};
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
#endif
{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
bool operator==
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
@@ -1390,65 +1375,65 @@
}
}
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator!=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
#endif
{ return !(x == y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
#endif
{ return y < x; }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator<=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
#endif
{ return !(y < x); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline bool operator>=
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(const splaytree_impl<T, Options...> &x, const splaytree_impl<T, Options...> &y)
#else
(const splaytree_impl<Config> &x, const splaytree_impl<Config> &y)
#endif
{ return !(x < y); }
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
#endif
inline void swap
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
(splaytree_impl<T, Options...> &x, splaytree_impl<T, Options...> &y)
#else
(splaytree_impl<Config> &x, splaytree_impl<Config> &y)
@@ -1456,15 +1441,23 @@
{ x.swap(y); }
/// @cond
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1 = none, class O2 = none
- , class O3 = none, class O4 = none
- , class O5 = none, class O6 = none
- , class O7 = none
- >
+ , class O3 = none, class O4 = none>
+#else
+template<class T, class ...Options>
+#endif
struct make_splaytree_opt
{
typedef typename pack_options
- < splay_set_defaults<T>, O1, O2, O3, O4>::type packed_options;
+ < splay_set_defaults<T>,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef typename detail::get_value_traits
<T, typename packed_options::value_traits>::type value_traits;
@@ -1479,7 +1472,7 @@
//! Helper metafunction to define a \c splaytree that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
@@ -1489,19 +1482,41 @@
{
/// @cond
typedef splaytree_impl
- < typename make_splaytree_opt<T, O1, O2, O3, O4>::type
+ < typename make_splaytree_opt<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class O1, class O2, class O3, class O4>
+#else
+template<class T, class ...Options>
+#endif
class splaytree
- : public make_splaytree<T, O1, O2, O3, O4>::type
+ : public make_splaytree<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_splaytree
- <T, O1, O2, O3, O4>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type Base;
public:
typedef typename Base::value_compare value_compare;
Modified: trunk/boost/intrusive/splaytree_algorithms.hpp
==============================================================================
--- trunk/boost/intrusive/splaytree_algorithms.hpp (original)
+++ trunk/boost/intrusive/splaytree_algorithms.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -870,7 +870,7 @@
if(NodeTraits::get_parent(g) == p)
NodeTraits::set_parent(g, n);
else{//must be ( g->right == p )
- assert(0);
+ BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
NodeTraits::set_right(g, n);
}
}
Modified: trunk/boost/intrusive/unordered_set.hpp
==============================================================================
--- trunk/boost/intrusive/unordered_set.hpp (original)
+++ trunk/boost/intrusive/unordered_set.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -56,7 +56,7 @@
//!
//! Since no automatic rehashing is done, iterators are never invalidated when
//! inserting or erasing elements. Iterators are only invalidated when rehasing.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -268,18 +268,24 @@
{ table_.swap(other.table_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes that compare equal and produce the same
+ //! hash than the original node.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. The hash function and the equality
+ //! predicate are copied from the source.
//!
- //! If cloner throws, all cloned elements are unlinked and disposed
+ //! If store_hash option is true, this method does not use the hash function.
+ //!
+ //! If any operation throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws. Basic guarantee.
+ //! <b>Throws</b>: If cloner or hasher throw or hash or equality predicate copying
+ //! throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer)
{ table_.clone_from(src.table_, cloner, disposer); }
@@ -920,6 +926,8 @@
//!
//! <b>Effects</b>: Updates the internal reference with the new bucket erases
//! the values from the old bucket and inserts then in the new one.
+ //!
+ //! If store_hash option is true, this method does not use the hash function.
//!
//! <b>Complexity</b>: Average case linear in this->size(), worst case quadratic.
//!
@@ -927,6 +935,32 @@
void rehash(const bucket_traits &new_bucket_traits)
{ table_.rehash(new_bucket_traits); }
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ //!
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(bool grow = true)
+ { return table_.incremental_rehash(grow); }
+
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(const bucket_traits &new_bucket_traits)
+ { return table_.incremental_rehash(new_bucket_traits); }
+
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ size_type split_count() const
+ { return table_.split_count(); }
+
//! <b>Effects</b>: Returns the nearest new bucket count optimized for
//! the container that is bigger than n. This suggestion can be used
//! to create bucket arrays with a size that will usually improve
@@ -954,14 +988,14 @@
//! Helper metafunction to define an \c unordered_set that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
, class O5 = none, class O6 = none
, class O7 = none, class O8 = none
- , class O9 = none
+ , class O9 = none, class O10= none
>
#endif
struct make_unordered_set
@@ -969,19 +1003,42 @@
/// @cond
typedef unordered_set_impl
< typename make_hashtable_opt
- <T, true, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
+ <T, true,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9>
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
+#else
+template<class T, class ...Options>
+#endif
class unordered_set
- : public make_unordered_set<T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
+ : public make_unordered_set<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_unordered_set
- <T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type Base;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
@@ -1052,7 +1109,7 @@
//!
//! Since no automatic rehashing is done, iterators are never invalidated when
//! inserting or erasing elements. Iterators are only invalidated when rehasing.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
template<class T, class ...Options>
#else
template<class Config>
@@ -1265,18 +1322,24 @@
{ table_.swap(other.table_); }
//! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
+ //! Cloner should yield to nodes that compare equal and produce the same
+ //! hash than the original node.
//!
//! <b>Effects</b>: Erases all the elements from *this
//! calling Disposer::operator()(pointer), clones all the
//! elements from src calling Cloner::operator()(const_reference )
- //! and inserts them on *this.
+ //! and inserts them on *this. The hash function and the equality
+ //! predicate are copied from the source.
//!
- //! If cloner throws, all cloned elements are unlinked and disposed
+ //! If store_hash option is true, this method does not use the hash function.
+ //!
+ //! If any operation throws, all cloned elements are unlinked and disposed
//! calling Disposer::operator()(pointer).
//!
//! <b>Complexity</b>: Linear to erased plus inserted elements.
//!
- //! <b>Throws</b>: If cloner throws.
+ //! <b>Throws</b>: If cloner or hasher throw or hash or equality predicate copying
+ //! throws. Basic guarantee.
template <class Cloner, class Disposer>
void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer)
{ table_.clone_from(src.table_, cloner, disposer); }
@@ -1854,6 +1917,8 @@
//!
//! <b>Effects</b>: Updates the internal reference with the new bucket erases
//! the values from the old bucket and inserts then in the new one.
+ //!
+ //! If store_hash option is true, this method does not use the hash function.
//!
//! <b>Complexity</b>: Average case linear in this->size(), worst case quadratic.
//!
@@ -1861,6 +1926,32 @@
void rehash(const bucket_traits &new_bucket_traits)
{ table_.rehash(new_bucket_traits); }
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ //!
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(bool grow = true)
+ { return table_.incremental_rehash(grow); }
+
+ //! <b>Note</b>: this method is only available if incremental<true> option is activated.
+ bool incremental_rehash(const bucket_traits &new_bucket_traits)
+ { return table_.incremental_rehash(new_bucket_traits); }
+
+ //! <b>Requires</b>:
+ //!
+ //! <b>Effects</b>:
+ //!
+ //! <b>Complexity</b>:
+ //!
+ //! <b>Throws</b>:
+ size_type split_count() const
+ { return table_.split_count(); }
+
//! <b>Effects</b>: Returns the nearest new bucket count optimized for
//! the container that is bigger than n. This suggestion can be used
//! to create bucket arrays with a size that will usually improve
@@ -1888,14 +1979,14 @@
//! Helper metafunction to define an \c unordered_multiset that yields to the same type when the
//! same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class T, class ...Options>
#else
template<class T, class O1 = none, class O2 = none
, class O3 = none, class O4 = none
, class O5 = none, class O6 = none
, class O7 = none, class O8 = none
- , class O9 = none
+ , class O9 = none, class O10= none
>
#endif
struct make_unordered_multiset
@@ -1903,19 +1994,42 @@
/// @cond
typedef unordered_multiset_impl
< typename make_hashtable_opt
- <T, false, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
+ <T, false,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
> implementation_defined;
/// @endcond
typedef implementation_defined type;
};
#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
-template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9>
+
+#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+template<class T, class O1, class O2, class O3, class O4, class O5, class O6, class O7, class O8, class O9, class O10>
+#else
+template<class T, class ...Options>
+#endif
class unordered_multiset
- : public make_unordered_multiset<T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type
+ : public make_unordered_multiset<T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type
{
typedef typename make_unordered_multiset
- <T, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type Base;
+ <T,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4, O5, O6, O7, O8, O9, O10
+ #else
+ Options...
+ #endif
+ >::type Base;
//Assert if passed value traits are compatible with the type
BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
Modified: trunk/boost/intrusive/unordered_set_hook.hpp
==============================================================================
--- trunk/boost/intrusive/unordered_set_hook.hpp (original)
+++ trunk/boost/intrusive/unordered_set_hook.hpp 2008-10-11 09:14:49 EDT (Sat, 11 Oct 2008)
@@ -153,7 +153,7 @@
//! Helper metafunction to define a \c unordered_set_base_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -162,7 +162,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_uset_node_algo<typename packed_options::void_pointer
@@ -201,15 +207,21 @@
//! \c optimize_multikey<> will tell the hook to store a link to form a group
//! with other value with the same value to speed up searches and insertions
//! in unordered_multisets with a great number of with equivalent keys.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class unordered_set_base_hook
- : public make_unordered_set_base_hook<O1, O2, O3, O4>::type
+ : public make_unordered_set_base_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
@@ -279,7 +291,7 @@
//! Helper metafunction to define a \c unordered_set_member_hook that yields to the same
//! type when the same options (either explicitly or implicitly) are used.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1 = none, class O2 = none, class O3 = none, class O4 = none>
@@ -288,7 +300,13 @@
{
/// @cond
typedef typename pack_options
- < hook_defaults, O1, O2, O3, O4>::type packed_options;
+ < hook_defaults,
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
typedef detail::generic_hook
< get_uset_node_algo< typename packed_options::void_pointer
@@ -318,15 +336,21 @@
//!
//! \c store_hash<> will tell the hook to store the hash of the value
//! to speed up rehashings.
-#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+#if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
template<class ...Options>
#else
template<class O1, class O2, class O3, class O4>
#endif
class unordered_set_member_hook
- : public make_unordered_set_member_hook<O1, O2, O3, O4>::type
+ : public make_unordered_set_member_hook<
+ #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type
{
- #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
+ #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
//! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link
//! initializes the node to an unlinked state.
//!
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk