From 7517211e4a3b241169f3e6c312e5aedc28ee0954 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 24 Jan 2009 16:53:03 +0000 Subject: [PATCH 01/29] Documentation fixes for intrusive: restore the reference documentation and fix some spelling mistakes. [SVN r50755] --- doc/intrusive.qbk | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index eb9df46..b8960a4 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -203,7 +203,7 @@ Intrusive containers have also downsides: * Analyzing the thread safety of a program that uses containers is harder with intrusive containers, because the container might be modified indirectly without an explicit call to a container member. -[table Summay of intrusive containers advantages and disadvantages +[table Summary of intrusive containers advantages and disadvantages [[Issue] [Intrusive] [Non-intrusive]] [[Memory management] [External] [Internal through allocator]] [[Insertion/Erasure time] [Faster] [Slower]] @@ -318,7 +318,7 @@ and optionally, the user can specify options. We have 3 option types: * [*`constant_time_size`]: Specifies if a constant time `size()` function is demanded for the container. This will instruct the intrusive container to store an additional member to keep track of the current size of the - container. By default, contant-time size is activated. + container. By default, constant-time size is activated. * [*`size_type`]: Specifies a type that can hold the size of the container. This type will be the type returned by `list.size()` @@ -464,7 +464,7 @@ issue and: * the computation of an iterator to an element from a pointer or reference to that element should be a constant time operation. * it's important to achieve a well-known worst-time system response. -* localization of data (e.g. for cache hit optimization) leads to measureable effects. +* localization of data (e.g. for cache hit optimization) leads to measurable effects. The last point is important if you have a lot of containers over a set of elements. E.g. if you have a vector of objects (say, `std::vector`), and you also have a list @@ -692,7 +692,7 @@ There is a reason for this: without referring to the container. This auto-unlink feature is useful in certain applications -but it must be used [*very carefuly]: +but it must be used [*very carefully]: * If several threads are using the same container the destructor of the auto-unlink hook will be called without any thread synchronization so removing the object is @@ -779,7 +779,7 @@ linear time complexity, even some that usually are constant time, like [classref boost::intrusive::slist::swap swap]. [classref boost::intrusive::slist slist] only provides forward iterators. -For most cases, a doubly linked list is preferrable because it offers more +For most cases, a doubly linked list is preferable because it offers more constant-time functions with a slightly bigger size overhead. However, for some applications like constructing more elaborate containers, singly linked lists are essential @@ -969,7 +969,7 @@ Now let's see a small example using both hooks: [*Boost.Intrusive] also offers associative containers that can be very useful when creating more complex associative containers, like containers maintaining one or more indices with different sorting semantics. Boost.Intrusive associative -containers, like most STL associative container implemenatations are based on +containers, like most STL associative container implementations are based on red-black trees. The memory overhead of these containers is usually 3 pointers and a bit (with @@ -1192,7 +1192,7 @@ Apart from them, these hooks offer additional options: container. When this option is used, the unordered container will store the calculated hash value in the hook and rehashing operations won't need to recalculate the hash of the value. - This option will improve the perfomance of unordered containers when + This option will improve the performance of unordered containers when rehashing is frequent or hashing the value is a slow operation. Default: `store_hash`. @@ -1801,7 +1801,7 @@ behavior may be outweighed by better expected-case behavior, as the most importa This means most important objects will be retrieved faster than less important items and for items keys with equal keys most important objects will be found first. These properties are important for some applications. -The priority comparison will be provided just like the key comparison, via a funcion object that will be +The priority comparison will be provided just like the key comparison, via a function object that will be stored in the intrusive container. This means that the priority can be stored in the value to be introduced in the treap or computed on flight (via hashing or similar). @@ -2065,7 +2065,7 @@ and [classref boost::intrusive::unordered_set unordered_set] reference for more With multiple ordered and unordered associative containers ([classref boost::intrusive::multiset multiset] and [classref boost::intrusive::unordered_multiset unordered_multiset]) there is -no need for these advanced insertion functions, since insertions are always succesful. +no need for these advanced insertion functions, since insertions are always successful. [endsect] @@ -2240,7 +2240,7 @@ For unordered associative containers On the other hand, `local_iterator_to` functions have their `s_local_iterator_to` static alternatives. -Alternative static functions are available under certain circunstances +Alternative static functions are available under certain circumstances explained in the [link intrusive.value_traits.stateful_value_traits Stateful value traits] section; if the programmer uses hooks provided by [*Boost.Intrusive], those functions will be available. @@ -3163,17 +3163,17 @@ class is empty: * If the class is not empty, a [*stateful] value traits is assumed. Node <-> Value transformations must be non-static functions. -Using stateful value traits it's possible to create containers of non-copyable/moveble objects [*without modifying] +Using stateful value traits it's possible to create containers of non-copyable/movable objects [*without modifying] the definition of the class to be inserted. This interesting property is achieved without using global variables (stateless value traits could use global variables to achieve the same goal), so: * [*Thread-safety guarantees]: Better thread-safety guarantees can be achieved with stateful - value traits, since accessing global resources might require syncronization primitives that + value traits, since accessing global resources might require synchronization primitives that can be avoided when using internal state. * [*Flexibility]: A stateful value traits type can be configured at run-time. * [*Run-time polymorphism]: A value traits might implement node <-> value transformations as virtual functions. A single container type could be - configured at run-time to use different node <-> value relatioships. + configured at run-time to use different node <-> value relationships. Stateful value traits have many advantages but also some downsides: @@ -3185,7 +3185,7 @@ Stateful value traits have many advantages but also some downsides: available because node <-> value transformations are not static. * [*Bigger iterators]: The size of some iterators is increased because the iterator needs to store a pointer to the stateful value traits to implement node to value - tranformations (e.g. `operator*()` and `operator->()`). + transformations (e.g. `operator*()` and `operator->()`). An easy and useful example of stateful value traits is when an array of values can be indirectly introduced in a list guaranteeing no additional allocation apart from the initial resource reservation: @@ -3335,7 +3335,7 @@ functions come in handy when implementing non-intrusive containers [*Boost.Intrusive] offers a wide range of containers but also allows the construction of custom containers reusing [*Boost.Intrusive] elements. -The programer might want to use node algorithms directly or +The programmer might want to use node algorithms directly or build special hooks that take advantage of an application environment. For example, the programmer can customize parts of [*Boost.Intrusive] @@ -3557,7 +3557,7 @@ containers. The dispersed pointer list, as with small values, has poor locality. The next test measures the time needed to complete calls to the member function `sort(Pred pred)`. Values (`test_class` and `itest_class`) and lists are created as explained in the -first section. The values will be sorted in ascending and descenting order each +first section. The values will be sorted in ascending and descending order each iteration. For example, if ['l] is a list: [c++] @@ -3706,7 +3706,7 @@ all the objects to be inserted in intrusive containers in containers like `std:: * New treap-based containers: treap, treap_set, treap_multiset. * Corrected compilation bug for Windows-based 64 bit compilers. * Corrected exception-safety bugs in container constructors. -* Updated documentation to show rvalue-references funcions instead of emulation functions. +* Updated documentation to show rvalue-references functions instead of emulation functions. [endsect] @@ -3762,7 +3762,7 @@ all the objects to be inserted in intrusive containers in containers like `std:: [endsect] -[section:acknowledgements Acknowledegements] +[section:acknowledgements Acknowledgements] [*Olaf Krzikalla] would like to thank: @@ -3799,7 +3799,7 @@ helpful discussions. [endsect] -[/xinclude autodoc.xml] +[xinclude autodoc.xml] [section:license_notices License notices] From 6527f4eb72296118bf9a6277453fe4afd7cc7cde Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 17 Feb 2009 10:05:58 +0000 Subject: [PATCH 02/29] Add PDF generation options to fix external links to point to the web site. Added a few more Boostbook based libs that were missed first time around. Fixed PDF naming issues. [SVN r51284] --- doc/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index f00fe39..0201f8a 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -55,4 +55,5 @@ boostbook standalone generate.section.toc.level=3 chunk.first.sections=1 autodoc + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html ; From e15d6b1cd9813db0002887d42583258da31b06d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 17 Feb 2009 17:03:10 +0000 Subject: [PATCH 03/29] Ticket #2755: compile error in boost_intrusive 1.38.0: a set of classes with protected destructor [SVN r51290] --- include/boost/intrusive/detail/mpl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 15954b9..20f50da 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -64,7 +64,7 @@ class is_convertible class false_t { char dummy[2]; }; static true_t dispatch(U); static false_t dispatch(...); - static T trigger(); + static const T &trigger(); public: static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); }; From ba8a73d677e2cb298aae2de5d029ab909fc87937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 24 Mar 2009 21:52:06 +0000 Subject: [PATCH 04/29] Changes for Boost.1.39 [SVN r51964] --- doc/intrusive.qbk | 11 ++- example/doc_any_hook.cpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 10 +-- .../intrusive/detail/parent_from_member.hpp | 3 +- include/boost/intrusive/detail/tree_node.hpp | 8 +- include/boost/intrusive/hashtable.hpp | 4 +- include/boost/intrusive/list.hpp | 34 ++++---- include/boost/intrusive/rbtree.hpp | 8 +- include/boost/intrusive/slist.hpp | 83 ++++++++++++------- proj/vc7ide/any_test/any_test.vcproj | 2 +- .../custom_bucket_traits.vcproj | 2 +- proj/vc7ide/default_hook/default_hook.vcproj | 2 +- .../external_value_traits.vcproj | 2 +- proj/vc7ide/list/list.vcproj | 2 +- .../make_functions/make_functions.vcproj | 2 +- .../stateful_value_traits.vcproj | 2 +- proj/vc7ide/to-do.txt | 2 + proj/vc7ide/virtual_base/virtual_base.vcproj | 2 +- test/slist_test.cpp | 22 +++++ test/unordered_multiset_test.cpp | 9 +- test/unordered_set_test.cpp | 2 +- 21 files changed, 138 insertions(+), 76 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index b8960a4..6ee4a03 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1280,7 +1280,9 @@ And they also can receive additional options: provides a bucket length that is not power of two. Default: `power_2_buckets`. -* [*`cache_begin`]: Due to its internal structure, finding the first +* [*`cache_begin`]: + [*Note: this option is not compatible with `auto_unlink` hooks]. + Due to its internal structure, finding the first element of an unordered container (`begin()` operation) is amortized constant-time. It's possible to speed up `begin()` and other operations related to it (like `clear()`) if the container caches internally the position @@ -3701,6 +3703,13 @@ all the objects to be inserted in intrusive containers in containers like `std:: [section:release_notes Release Notes] +[section:release_notes_boost_1_39_00 Boost 1.39 Release] + +* Optimized `list::merge` and `slist::merge` +* `list::sort` and `slist::sort` are now stable. + +[endsect] + [section:release_notes_boost_1_38_00 Boost 1.38 Release] * New treap-based containers: treap, treap_set, treap_multiset. diff --git a/example/doc_any_hook.cpp b/example/doc_any_hook.cpp index 15220dc..11991aa 100644 --- a/example/doc_any_hook.cpp +++ b/example/doc_any_hook.cpp @@ -34,7 +34,7 @@ int main() typedef any_to_slist_hook < base_hook< any_base_hook<> > > BaseSlistOption; typedef slist BaseSList; - //Define a member hook option that converts any_base_hook to a list hook + //Define a member hook option that converts any_member_hook to a list hook typedef any_to_list_hook< member_hook < MyClass, any_member_hook<>, &MyClass::member_hook_> > MemberListOption; typedef list MemberList; diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index 43cc975..35628f2 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -26,18 +26,18 @@ class ebo_functor_holder_impl ebo_functor_holder_impl() {} ebo_functor_holder_impl(const T& t) - : t(t) + : t_(t) {} template ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2) - : t(arg1, arg2) + : t_(arg1, arg2) {} - T& get(){return t;} - const T& get()const{return t;} + T& get(){return t_;} + const T& get()const{return t_;} private: - T t; + T t_; }; template diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index c99ac6c..c750ad8 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -15,7 +15,8 @@ #include #include -#if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL)) +#if defined(BOOST_MSVC) || ((defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && defined(BOOST_INTEL)) + #define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER #include #endif diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index be3c976..146f758 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -99,8 +99,8 @@ class tree_iterator : members_ (0, 0) {} - explicit tree_iterator(node_ptr node, const Container *cont_ptr) - : members_ (node, cont_ptr) + explicit tree_iterator(node_ptr nodeptr, const Container *cont_ptr) + : members_ (nodeptr, cont_ptr) {} tree_iterator(tree_iterator const& other) @@ -110,8 +110,8 @@ class tree_iterator const node_ptr &pointed_node() const { return members_.nodeptr_; } - tree_iterator &operator=(const node_ptr &node) - { members_.nodeptr_ = node; return static_cast(*this); } + tree_iterator &operator=(const node_ptr &nodeptr) + { members_.nodeptr_ = nodeptr; return static_cast(*this); } public: tree_iterator& operator++() diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 0db5f23..d8605aa 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -718,6 +718,8 @@ class hashtable_impl //Constant-time size is incompatible with auto-unlink hooks! BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + //Cache begin is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(cache_begin && ((int)real_value_traits::link_mode == (int)auto_unlink))); template node_cast_adaptor > @@ -871,7 +873,7 @@ class hashtable_impl //! Effects: Returns true if the container is empty. //! - //! Complexity: if constant-time size and cache_last options are disabled, + //! Complexity: if constant-time size and cache_begin options are disabled, //! average constant time (worst case, with empty() == true: O(this->bucket_count()). //! Otherwise constant. //! diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index b1f944a..d38d960 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -978,7 +978,8 @@ class list_impl carry.splice(carry.cbegin(), *this, this->cbegin()); int i = 0; while(i < fill && !counter[i].empty()) { - carry.merge(counter[i++], p); + counter[i].merge(carry, p); + carry.swap(counter[i++]); } carry.swap(counter[i]); if(i == fill) @@ -1021,21 +1022,26 @@ class list_impl template void merge(list_impl& x, Predicate p) { - const_iterator e(this->end()); - const_iterator bx(x.begin()); - const_iterator ex(x.end()); - - for (const_iterator b = this->cbegin(); b != e; ++b) { - size_type n(0); - const_iterator ix(bx); - while(ix != ex && p(*ix, *b)){ - ++ix; ++n; + const_iterator e(this->cend()), ex(x.cend()); + const_iterator b(this->cbegin()); + while(!x.empty()){ + const_iterator ix(x.cbegin()); + while (b != e && !p(*ix, *b)){ + ++b; + } + if(b == e){ + //Now transfer the rest to the end of the container + this->splice(e, x); + break; + } + else{ + size_type n(0); + do{ + ++ix; ++n; + } while(ix != ex && p(*ix, *b)); + this->splice(b, x, x.begin(), ix, n); } - this->splice(b, x, bx, ix, n); - bx = ix; } - //Now transfer the rest at the end of the container - this->splice(e, x); } //! Effects: Reverses the order of elements in the list. diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index fa7aa4a..572b545 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -513,9 +513,9 @@ class rbtree_impl template void insert_equal(Iterator b, Iterator e) { - iterator end(this->end()); + iterator iend(this->end()); for (; b != e; ++b) - this->insert_equal(end, *b); + this->insert_equal(iend, *b); } //! Requires: value must be an lvalue @@ -579,9 +579,9 @@ class rbtree_impl void insert_unique(Iterator b, Iterator e) { if(this->empty()){ - iterator end(this->end()); + iterator iend(this->end()); for (; b != e; ++b) - this->insert_unique(end, *b); + this->insert_unique(iend, *b); } else{ for (; b != e; ++b) diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index a08752e..e430fb1 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -598,7 +598,7 @@ class slist_impl void swap(slist_impl& other) { if(cache_last){ - this->priv_swap_cache_last(other); + priv_swap_cache_last(this, &other); } else{ this->priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_()); @@ -1264,6 +1264,7 @@ class slist_impl carry.splice_after(carry.cbefore_begin(), *this, this->cbefore_begin()); int i = 0; while(i < fill && !counter[i].empty()) { + carry.swap(counter[i]); last_inserted = carry.merge(counter[i++], p); } BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty()); @@ -1340,24 +1341,26 @@ class slist_impl template iterator merge(slist_impl& x, Predicate p) { - 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()) { - const_iterator ix(ax); - const_iterator cx; - size_type n(0); - while(++(cx = ix) != ex && p(*cx, *a_next)){ - ++ix; ++n; + const_iterator e(this->cend()), ex(x.cend()), bb(this->cbefore_begin()), + bb_next, last_inserted(e); + while(!x.empty()){ + const_iterator ibx_next(x.cbefore_begin()), ibx(ibx_next++); + while (++(bb_next = bb) != e && !p(*ibx_next, *bb_next)){ + bb = bb_next; } - if(ax != ix){ - this->splice_after(a, x, ax, ix, n); - last_inserted = ix; + if(bb_next == e){ + //Now transfer the rest to the end of the container + last_inserted = this->splice_after(bb, x); + break; + } + else{ + size_type n(0); + do{ + ibx = ibx_next; ++n; + } while(++(ibx_next = ibx) != ex && p(*ibx_next, *bb_next)); + this->splice_after(bb, x, x.before_begin(), ibx, n); + last_inserted = ibx; } - a = a_next; - } - if (!x.empty()){ - last_inserted = this->splice_after(a, x); } return last_inserted.unconst(); } @@ -1711,22 +1714,40 @@ class slist_impl } } - void priv_swap_cache_last(slist_impl &other) + static void priv_swap_cache_last(slist_impl *this_impl, slist_impl *other_impl) { - node_ptr other_last(other.get_last_node()); - node_ptr this_last(this->get_last_node()); - node_ptr other_bfirst(other.get_root_node()); - node_ptr this_bfirst(this->get_root_node()); - node_algorithms::transfer_after(this_bfirst, other_bfirst, other_last); - node_algorithms::transfer_after(other_bfirst, other_last != other_bfirst? other_last : this_bfirst, this_last); - node_ptr tmp(this->get_last_node()); - this->set_last_node(other.get_last_node()); - other.set_last_node(tmp); - if(this->get_last_node() == other_bfirst){ - this->set_last_node(this_bfirst); + bool other_was_empty = false; + if(this_impl->empty()){ + //Check if both are empty or + if(other_impl->empty()) + return; + //If this is empty swap pointers + slist_impl *tmp = this_impl; + this_impl = other_impl; + other_impl = tmp; + other_was_empty = true; } - if(other.get_last_node() == this_bfirst){ - other.set_last_node(other_bfirst); + else{ + other_was_empty = other_impl->empty(); + } + + //Precondition: this is not empty + node_ptr other_old_last(other_impl->get_last_node()); + node_ptr other_bfirst(other_impl->get_root_node()); + node_ptr this_bfirst(this_impl->get_root_node()); + node_ptr this_old_last(this_impl->get_last_node()); + + //Move all nodes from this to other's beginning + node_algorithms::transfer_after(other_bfirst, this_bfirst, this_old_last); + other_impl->set_last_node(this_old_last); + + if(other_was_empty){ + this_impl->set_last_node(this_bfirst); + } + else{ + //Move trailing nodes from other to this + node_algorithms::transfer_after(this_bfirst, this_old_last, other_old_last); + this_impl->set_last_node(other_old_last); } } diff --git a/proj/vc7ide/any_test/any_test.vcproj b/proj/vc7ide/any_test/any_test.vcproj index b053349..e99365d 100644 --- a/proj/vc7ide/any_test/any_test.vcproj +++ b/proj/vc7ide/any_test/any_test.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj b/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj index a396174..2c873b8 100644 --- a/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj +++ b/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/default_hook/default_hook.vcproj b/proj/vc7ide/default_hook/default_hook.vcproj index 9c26fb7..e6c1b7f 100644 --- a/proj/vc7ide/default_hook/default_hook.vcproj +++ b/proj/vc7ide/default_hook/default_hook.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/external_value_traits/external_value_traits.vcproj b/proj/vc7ide/external_value_traits/external_value_traits.vcproj index 87ebd51..6f0b875 100644 --- a/proj/vc7ide/external_value_traits/external_value_traits.vcproj +++ b/proj/vc7ide/external_value_traits/external_value_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/list/list.vcproj b/proj/vc7ide/list/list.vcproj index e5e510b..8f5817b 100644 --- a/proj/vc7ide/list/list.vcproj +++ b/proj/vc7ide/list/list.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/make_functions/make_functions.vcproj b/proj/vc7ide/make_functions/make_functions.vcproj index cf926ce..572aa02 100644 --- a/proj/vc7ide/make_functions/make_functions.vcproj +++ b/proj/vc7ide/make_functions/make_functions.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj b/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj index 72cbe3b..a5b898e 100644 --- a/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj +++ b/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/to-do.txt b/proj/vc7ide/to-do.txt index f62414d..534314c 100644 --- a/proj/vc7ide/to-do.txt +++ b/proj/vc7ide/to-do.txt @@ -24,3 +24,5 @@ -> revise strong exception safety concepts for treap::erase functions. What happens with range deletions? -> Assure stable order for optimize_multikey and inverse order otherwise +-> linear slist's splice_after(..., slist &x) can be optimized if *this is empty +-> optimize slist::merge like list::merge diff --git a/proj/vc7ide/virtual_base/virtual_base.vcproj b/proj/vc7ide/virtual_base/virtual_base.vcproj index b5f6f66..7d87163 100644 --- a/proj/vc7ide/virtual_base/virtual_base.vcproj +++ b/proj/vc7ide/virtual_base/virtual_base.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="FALSE" + DisableLanguageExtensions="TRUE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 569c1ae..ff0bd7f 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -417,6 +417,28 @@ void test_slist { int init_values [] = { 2 }; TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } } + { //Now test swap when testlist2 is empty + list_type testlist1 (&values[0], &values[0] + 2); + list_type testlist2; + testlist1.swap(testlist2); + BOOST_TEST (testlist1.empty()); + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist2.begin() ); } + } + { //Now test swap when testlist1 is empty + list_type testlist2 (&values[0], &values[0] + 2); + list_type testlist1; + testlist1.swap(testlist2); + BOOST_TEST (testlist2.empty()); + { int init_values [] = { 1, 2 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testlist1.begin() ); } + } + { //Now test when both are empty + list_type testlist1, testlist2; + testlist2.swap(testlist1); + BOOST_TEST (testlist1.empty() && testlist2.empty()); + } + if(!list_type::linear) { list_type testlist1 (&values[0], &values[0] + 2); diff --git a/test/unordered_multiset_test.cpp b/test/unordered_multiset_test.cpp index 868d264..206605d 100644 --- a/test/unordered_multiset_test.cpp +++ b/test/unordered_multiset_test.cpp @@ -719,7 +719,6 @@ class test_main_template , false , Incremental >::test_all(data); - return 0; } }; @@ -740,7 +739,7 @@ class test_main_template < value_type , typename hooks::base_hook_type >::type - , true + , false , false , Incremental >::test_all(data); @@ -752,7 +751,7 @@ class test_main_template , &value_type::node_ > >::type - , false + , true , false , Incremental >::test_all(data); @@ -761,8 +760,8 @@ class test_main_template < value_type , typename hooks::auto_base_hook_type >::type - , true - , true + , false + , false , Incremental >::test_all(data); diff --git a/test/unordered_set_test.cpp b/test/unordered_set_test.cpp index b84414b..f6b5e48 100644 --- a/test/unordered_set_test.cpp +++ b/test/unordered_set_test.cpp @@ -623,7 +623,7 @@ class test_main_template < value_type , typename hooks::auto_base_hook_type >::type - , true + , false , true , incremental >::test_all(data); From f532ae12e77a2036b7b0d2b92b9f4c6c732e3507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 25 Mar 2009 18:18:04 +0000 Subject: [PATCH 05/29] Changes for Boost.1.39 [SVN r51973] --- doc/intrusive.qbk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index 6ee4a03..69f11cd 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3707,6 +3707,13 @@ all the objects to be inserted in intrusive containers in containers like `std:: * Optimized `list::merge` and `slist::merge` * `list::sort` and `slist::sort` are now stable. +* Fixed bugs + [@https://svn.boost.org/trac/boost/ticket/2689 #2689], + [@https://svn.boost.org/trac/boost/ticket/2755 #2755], + [@https://svn.boost.org/trac/boost/ticket/2786 #2786], + [@https://svn.boost.org/trac/boost/ticket/2807 #2807], + [@https://svn.boost.org/trac/boost/ticket/2810 #2810], + [@https://svn.boost.org/trac/boost/ticket/2862 #2862]. [endsect] From 75f7139c3f1dc8cb6ba250876c0920caa54acb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 16 Apr 2009 07:05:08 +0000 Subject: [PATCH 06/29] Fixed C++0x and MacOS X bugs [SVN r52416] --- doc/Jamfile.v2 | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 0201f8a..f00fe39 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -55,5 +55,4 @@ boostbook standalone generate.section.toc.level=3 chunk.first.sections=1 autodoc - pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html ; From eeb14b00a6b06bdbe45a6079fe8e11ce93982557 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Wed, 20 May 2009 19:19:00 +0000 Subject: [PATCH 07/29] Fixed most tab and min/max issues from trunk inspection report [SVN r53141] --- include/boost/intrusive/priority_compare.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index 19d4265..9689851 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -23,7 +23,7 @@ namespace intrusive { template struct priority_compare - : public std::binary_function + : public std::binary_function { bool operator()(const T &val, const T &val2) const { From 7f6921c717d38f66a287bd6f09a37f479a525bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 25 Jun 2009 16:08:20 +0000 Subject: [PATCH 08/29] Boost 1.40 changes [SVN r54336] --- .../boost/intrusive/avltree_algorithms.hpp | 208 +++++------------- .../intrusive/detail/tree_algorithms.hpp | 84 +++---- 2 files changed, 94 insertions(+), 198 deletions(-) diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 307dbc8..6385ff9 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -664,8 +664,7 @@ class avltree_algorithms static void rebalance_after_erasure(node_ptr header, node_ptr x, node_ptr x_parent) { - node_ptr root = NodeTraits::get_parent(header); - while (x != root) { + for (node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)) { const balance x_parent_balance = NodeTraits::get_balance(x_parent); if(x_parent_balance == NodeTraits::zero()){ NodeTraits::set_balance(x_parent, @@ -686,16 +685,14 @@ class avltree_algorithms if (NodeTraits::get_balance(a) == NodeTraits::positive()) { // a MUST have a right child BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(a)); - rotate_left_right(x_parent, root); - + rotate_left_right(x_parent, header); x = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x); } else { - rotate_right(x_parent, root); + rotate_right(x_parent, header); x = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x); - } // if changed from negative to NodeTraits::positive(), no need to check above @@ -718,15 +715,15 @@ class avltree_algorithms if (NodeTraits::get_balance(a) == NodeTraits::negative()) { // a MUST have then a left child BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(a)); - rotate_right_left(x_parent, root); + rotate_right_left(x_parent, header); x = NodeTraits::get_parent(x_parent); x_parent = NodeTraits::get_parent(x); } else { - rotate_left(x_parent, root); - x = NodeTraits::get_parent(x_parent); - x_parent = NodeTraits::get_parent(x); + rotate_left(x_parent, header); + x = NodeTraits::get_parent(x_parent); + x_parent = NodeTraits::get_parent(x); } // if changed from NodeTraits::positive() to negative, no need to check above if (NodeTraits::get_balance(x) == NodeTraits::negative()){ @@ -738,17 +735,14 @@ class avltree_algorithms BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } } - NodeTraits::set_parent(header, root); } - static void rebalance_after_insertion(node_ptr header, node_ptr x) { - node_ptr root = NodeTraits::get_parent(header); NodeTraits::set_balance(x, NodeTraits::zero()); // Rebalance. - while (x != root){ + for(node_ptr root = NodeTraits::get_parent(header); x != root; root = NodeTraits::get_parent(header)){ const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x)); if(x_parent_balance == NodeTraits::zero()){ @@ -765,9 +759,9 @@ class avltree_algorithms NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); else{ // x is a right child, needs rebalancing if (NodeTraits::get_balance(x) == NodeTraits::negative()) - rotate_right_left(NodeTraits::get_parent(x), root); + rotate_right_left(NodeTraits::get_parent(x), header); else - rotate_left(NodeTraits::get_parent(x), root); + rotate_left(NodeTraits::get_parent(x), header); } break; } @@ -775,9 +769,9 @@ class avltree_algorithms // if x is a left child, needs rebalancing if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) { if (NodeTraits::get_balance(x) == NodeTraits::positive()) - rotate_left_right(NodeTraits::get_parent(x), root); + rotate_left_right(NodeTraits::get_parent(x), header); else - rotate_right(NodeTraits::get_parent(x), root); + rotate_right(NodeTraits::get_parent(x), header); } else NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); @@ -787,10 +781,32 @@ class avltree_algorithms BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached } } - NodeTraits::set_parent(header, root); } - static void rotate_left_right(node_ptr a, node_ptr &root) + static void left_right_balancing(node_ptr a, node_ptr b, node_ptr c) + { + // balancing... + const balance c_balance = NodeTraits::get_balance(c); + const balance zero_balance = NodeTraits::zero(); + NodeTraits::set_balance(c, zero_balance); + if(c_balance == NodeTraits::negative()){ + NodeTraits::set_balance(a, NodeTraits::positive()); + NodeTraits::set_balance(b, zero_balance); + } + else if(c_balance == zero_balance){ + NodeTraits::set_balance(a, zero_balance); + NodeTraits::set_balance(b, zero_balance); + } + else if(c_balance == NodeTraits::positive()){ + NodeTraits::set_balance(a, zero_balance); + NodeTraits::set_balance(b, NodeTraits::negative()); + } + else{ + BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached + } + } + + static void rotate_left_right(const node_ptr a, node_ptr hdr) { // | | // // a(-2) c // @@ -802,52 +818,12 @@ class avltree_algorithms // / \ // // e f // node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b); - - // switch - NodeTraits::set_left(a, NodeTraits::get_right(c)); - NodeTraits::set_right(b, NodeTraits::get_left(c)); - - NodeTraits::set_right(c, a); - NodeTraits::set_left(c, b); - - // set the parents - NodeTraits::set_parent(c, NodeTraits::get_parent(a)); - NodeTraits::set_parent(a, c); - NodeTraits::set_parent(b, c); - - if (NodeTraits::get_left(a)) // do we have f? - NodeTraits::set_parent(NodeTraits::get_left(a), a); - if (NodeTraits::get_right(b)) // do we have e? - NodeTraits::set_parent(NodeTraits::get_right(b), b); - - if (a==root) root = c; - else // a had a parent, his child is now c - if (a == NodeTraits::get_left(NodeTraits::get_parent(c))) - NodeTraits::set_left(NodeTraits::get_parent(c), c); - else - NodeTraits::set_right(NodeTraits::get_parent(c), c); - - // balancing... - const balance c_balance = NodeTraits::get_balance(c); - if(c_balance == NodeTraits::negative()){ - NodeTraits::set_balance(a, NodeTraits::positive()); - NodeTraits::set_balance(b, NodeTraits::zero()); - } - else if(c_balance == NodeTraits::zero()){ - NodeTraits::set_balance(a, NodeTraits::zero()); - NodeTraits::set_balance(b, NodeTraits::zero()); - } - else if(c_balance == NodeTraits::positive()){ - NodeTraits::set_balance(a, NodeTraits::zero()); - NodeTraits::set_balance(b, NodeTraits::negative()); - } - else{ - BOOST_INTRUSIVE_INVARIANT_ASSERT(false); // never reached - } - NodeTraits::set_balance(c, NodeTraits::zero()); + tree_algorithms::rotate_left(b, hdr); + tree_algorithms::rotate_right(a, hdr); + left_right_balancing(a, b, c); } - static void rotate_right_left(node_ptr a, node_ptr &root) + static void rotate_right_left(const node_ptr a, node_ptr hdr) { // | | // // a(pos) c // @@ -859,81 +835,15 @@ class avltree_algorithms // / \ // // e f // node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b); - - // switch - NodeTraits::set_right(a, NodeTraits::get_left(c)); - NodeTraits::set_left(b, NodeTraits::get_right(c)); - - NodeTraits::set_left(c, a); - NodeTraits::set_right(c, b); - - // set the parents - NodeTraits::set_parent(c, NodeTraits::get_parent(a)); - NodeTraits::set_parent(a, c); - NodeTraits::set_parent(b, c); - - if (NodeTraits::get_right(a)) // do we have e? - NodeTraits::set_parent(NodeTraits::get_right(a), a); - if (NodeTraits::get_left(b)) // do we have f? - NodeTraits::set_parent(NodeTraits::get_left(b), b); - - if (a==root) root = c; - else // a had a parent, his child is now c - if (a == NodeTraits::get_left(NodeTraits::get_parent(c))) - NodeTraits::set_left(NodeTraits::get_parent(c), c); - else - NodeTraits::set_right(NodeTraits::get_parent(c), c); - - // balancing... - const balance c_balance = NodeTraits::get_balance(c); - if(c_balance == NodeTraits::negative()){ - NodeTraits::set_balance(a, NodeTraits::zero()); - NodeTraits::set_balance(b, NodeTraits::positive()); - } - else if(c_balance == NodeTraits::zero()){ - NodeTraits::set_balance(a, NodeTraits::zero()); - NodeTraits::set_balance(b, NodeTraits::zero()); - } - else if(c_balance == NodeTraits::positive()){ - NodeTraits::set_balance(a, NodeTraits::negative()); - NodeTraits::set_balance(b, NodeTraits::zero()); - } - else{ - BOOST_INTRUSIVE_INVARIANT_ASSERT(false); - } - NodeTraits::set_balance(c, NodeTraits::zero()); + tree_algorithms::rotate_right(b, hdr); + tree_algorithms::rotate_left(a, hdr); + left_right_balancing(b, a, c); } - static void rotate_left(node_ptr x, node_ptr & root) + static void rotate_left(const node_ptr x, node_ptr hdr) { - // | | // - // x(2) y(0) // - // / \ ==> / \ // - // n[a] y(1)n+2 n+1(0)x [c]n+1 // - // / \ / \ // - // n[b] [c]n+1 n[a] [b]n // - node_ptr y = NodeTraits::get_right(x); - - // switch - NodeTraits::set_right(x, NodeTraits::get_left(y)); - NodeTraits::set_left(y, x); - - // rearrange parents - NodeTraits::set_parent(y, NodeTraits::get_parent(x)); - NodeTraits::set_parent(x, y); - - // do we have [b]? - if (NodeTraits::get_right(x)) - NodeTraits::set_parent(NodeTraits::get_right(x), x); - - if (x == root) - root = y; - else - // need to reparent y - if (NodeTraits::get_left(NodeTraits::get_parent(y)) == x) - NodeTraits::set_left(NodeTraits::get_parent(y), y); - else - NodeTraits::set_right(NodeTraits::get_parent(y), y); + const node_ptr y = NodeTraits::get_right(x); + tree_algorithms::rotate_left(x, hdr); // reset the balancing factor if (NodeTraits::get_balance(y) == NodeTraits::positive()) { @@ -946,30 +856,10 @@ class avltree_algorithms } } - static void rotate_right(node_ptr x, node_ptr &root) + static void rotate_right(const node_ptr x, node_ptr hdr) { - node_ptr y = NodeTraits::get_left(x); - - // switch - NodeTraits::set_left(x, NodeTraits::get_right(y)); - NodeTraits::set_right(y, x); - - // rearrange parents - NodeTraits::set_parent(y, NodeTraits::get_parent(x)); - NodeTraits::set_parent(x, y); - - // do we have [b]? - if (NodeTraits::get_left(x)) - NodeTraits::set_parent(NodeTraits::get_left(x), x); - - if (x == root) - root = y; - else - // need to reparent y - if (NodeTraits::get_left(NodeTraits::get_parent(y)) == x) - NodeTraits::set_left(NodeTraits::get_parent(y), y); - else - NodeTraits::set_right(NodeTraits::get_parent(y), y); + const node_ptr y = NodeTraits::get_left(x); + tree_algorithms::rotate_right(x, hdr); // reset the balancing factor if (NodeTraits::get_balance(y) == NodeTraits::negative()) { diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 1fe196b..57d5206 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -1232,69 +1232,75 @@ class tree_algorithms //! Complexity: Constant. //! //! Throws: Nothing. - static bool is_right_child (node_ptr p) + static bool is_right_child(node_ptr p) { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; } - static void replace_own (node_ptr own, node_ptr x, node_ptr header) + //Fix header and own's parent data when replacing x with own, providing own's old data with parent + static void replace_own_impl(node_ptr own, node_ptr x, node_ptr header, node_ptr own_parent, bool own_was_left) { if(NodeTraits::get_parent(header) == own) NodeTraits::set_parent(header, x); - else if(is_left_child(own)) - NodeTraits::set_left(NodeTraits::get_parent(own), x); + else if(own_was_left) + NodeTraits::set_left(own_parent, x); else - NodeTraits::set_right(NodeTraits::get_parent(own), x); + NodeTraits::set_right(own_parent, x); } - static void rotate_left(node_ptr p, node_ptr header) + //Fix header and own's parent data when replacing x with own, supposing own + //links with its parent are still ok + static void replace_own(node_ptr own, node_ptr x, node_ptr header) { - node_ptr x = NodeTraits::get_right(p); - NodeTraits::set_right(p, NodeTraits::get_left(x)); - if(NodeTraits::get_left(x) != 0) - NodeTraits::set_parent(NodeTraits::get_left(x), p); - NodeTraits::set_parent(x, NodeTraits::get_parent(p)); - replace_own (p, x, header); + node_ptr own_parent(NodeTraits::get_parent(own)); + bool own_is_left(NodeTraits::get_left(own_parent) == own); + replace_own_impl(own, x, header, own_parent, own_is_left); + } + + // rotate parent p to left (no header and p's parent fixup) + static node_ptr rotate_left(node_ptr p) + { + node_ptr x(NodeTraits::get_right(p)); + node_ptr x_left(NodeTraits::get_left(x)); + NodeTraits::set_right(p, x_left); + if(x_left){ + NodeTraits::set_parent(x_left, p); + } NodeTraits::set_left(x, p); NodeTraits::set_parent(p, x); + return x; } - static void rotate_right(node_ptr p, node_ptr header) + // rotate parent p to left (with header and p's parent fixup) + static void rotate_left(node_ptr p, node_ptr header) + { + bool p_was_left(is_left_child(p)); + node_ptr p_old_parent(NodeTraits::get_parent(p)); + node_ptr x(rotate_left(p)); + NodeTraits::set_parent(x, p_old_parent); + replace_own_impl(p, x, header, p_old_parent, p_was_left); + } + + // rotate parent p to right (no header and p's parent fixup) + static node_ptr rotate_right(node_ptr p) { node_ptr x(NodeTraits::get_left(p)); node_ptr x_right(NodeTraits::get_right(x)); NodeTraits::set_left(p, x_right); - if(x_right) + if(x_right){ NodeTraits::set_parent(x_right, p); - NodeTraits::set_parent(x, NodeTraits::get_parent(p)); - replace_own (p, x, header); + } NodeTraits::set_right(x, p); NodeTraits::set_parent(p, x); - } - - // rotate node t with left child | complexity : constant | exception : nothrow - static node_ptr rotate_left(node_ptr t) - { - node_ptr x = NodeTraits::get_right(t); - NodeTraits::set_right(t, NodeTraits::get_left(x)); - - if( NodeTraits::get_right(t) != 0 ){ - NodeTraits::set_parent(NodeTraits::get_right(t), t ); - } - NodeTraits::set_left(x, t); - NodeTraits::set_parent(t, x); return x; } - // rotate node t with right child | complexity : constant | exception : nothrow - static node_ptr rotate_right(node_ptr t) + // rotate parent p to right (with header and p's parent fixup) + static void rotate_right(node_ptr p, node_ptr header) { - node_ptr x = NodeTraits::get_left(t); - NodeTraits::set_left(t, NodeTraits::get_right(x)); - if( NodeTraits::get_left(t) != 0 ){ - NodeTraits::set_parent(NodeTraits::get_left(t), t); - } - NodeTraits::set_right(x, t); - NodeTraits::set_parent(t, x); - return x; + bool p_was_left(is_left_child(p)); + node_ptr p_old_parent(NodeTraits::get_parent(p)); + node_ptr x(rotate_right(p)); + NodeTraits::set_parent(x, p_old_parent); + replace_own_impl(p, x, header, p_old_parent, p_was_left); } static void link(node_ptr header, node_ptr z, node_ptr par, bool left) From ccd4975b461e047ab616a8358f26a60e4d4fe298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 25 Jun 2009 16:26:25 +0000 Subject: [PATCH 09/29] Boost 1.40 changes [SVN r54339] --- doc/intrusive.qbk | 9 +++++++++ example/doc_avl_set.cpp | 2 +- example/doc_set.cpp | 2 +- example/doc_sg_set.cpp | 2 +- example/doc_splay_set.cpp | 2 +- test/avl_set_test.cpp | 1 + 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index 69f11cd..cb642f1 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3703,6 +3703,15 @@ all the objects to be inserted in intrusive containers in containers like `std:: [section:release_notes Release Notes] +[section:release_notes_boost_1_40_00 Boost 1.40 Release] + +* Code cleanup in tree_algorithms.hpp and avl_tree_algorithms.hpp +* Fixed bug + [@https://svn.boost.org/trac/boost/ticket/3164 #3164]. + +[endsect] + + [section:release_notes_boost_1_39_00 Boost 1.39 Release] * Optimized `list::merge` and `slist::merge` diff --git a/example/doc_avl_set.cpp b/example/doc_avl_set.cpp index 32d339b..985c136 100644 --- a/example/doc_avl_set.cpp +++ b/example/doc_avl_set.cpp @@ -34,7 +34,7 @@ class MyClass : public avl_set_base_hook > friend bool operator> (const MyClass &a, const MyClass &b) { return a.int_ > b.int_; } friend bool operator== (const MyClass &a, const MyClass &b) - { return a.int_ < b.int_; } + { return a.int_ == b.int_; } }; //Define an avl_set using the base hook that will store values in reverse order diff --git a/example/doc_set.cpp b/example/doc_set.cpp index c996038..49fbe9c 100644 --- a/example/doc_set.cpp +++ b/example/doc_set.cpp @@ -34,7 +34,7 @@ class MyClass : public set_base_hook > friend bool operator> (const MyClass &a, const MyClass &b) { return a.int_ > b.int_; } friend bool operator== (const MyClass &a, const MyClass &b) - { return a.int_ < b.int_; } + { return a.int_ == b.int_; } }; //Define a set using the base hook that will store values in reverse order diff --git a/example/doc_sg_set.cpp b/example/doc_sg_set.cpp index aa33258..5885b0e 100644 --- a/example/doc_sg_set.cpp +++ b/example/doc_sg_set.cpp @@ -33,7 +33,7 @@ class MyClass : public bs_set_base_hook<> friend bool operator> (const MyClass &a, const MyClass &b) { return a.int_ > b.int_; } friend bool operator== (const MyClass &a, const MyClass &b) - { return a.int_ < b.int_; } + { return a.int_ == b.int_; } }; //Define an sg_set using the base hook that will store values in reverse order diff --git a/example/doc_splay_set.cpp b/example/doc_splay_set.cpp index 8859165..87ed7e0 100644 --- a/example/doc_splay_set.cpp +++ b/example/doc_splay_set.cpp @@ -36,7 +36,7 @@ class MyClass friend bool operator> (const MyClass &a, const MyClass &b) { return a.int_ > b.int_; } friend bool operator== (const MyClass &a, const MyClass &b) - { return a.int_ < b.int_; } + { return a.int_ == b.int_; } }; //Define a set using the base hook that will store values in reverse order diff --git a/test/avl_set_test.cpp b/test/avl_set_test.cpp index 55e415c..8b4f16e 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -132,6 +132,7 @@ int main( int, char* [] ) test_main_template, false>()(); test_main_template()(); test_main_template, true>()(); + return boost::report_errors(); } From 3376090641d81e163a6d8500baf5a93d08172b80 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sun, 26 Jul 2009 00:49:56 +0000 Subject: [PATCH 10/29] Copyrights on CMakeLists.txt to keep them from clogging up the inspect reports. This is essentially the same commit as r55095 on the release branch. [SVN r55159] --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73434d8..3169cb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# +# Copyright Troy D. Straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt +# #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file # Add a variable to hold the headers for the library From cb7bd3a146078f389fa14b2a8aa1bee39f70cea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Aug 2009 04:42:52 +0000 Subject: [PATCH 11/29] minor typo [SVN r55564] --- doc/intrusive.qbk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index cb642f1..df7dded 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -7,8 +7,8 @@ [library Boost.Intrusive [quickbook 1.3] - [authors [Krzikalla, Olaf], [Gaztañaga, Ion]] - [copyright 2005 Olaf Krzikalla, 2006-2008 Ion Gaztañaga] + [authors [Krzikalla, Olaf], [Gaztanaga, Ion]] + [copyright 2005 Olaf Krzikalla, 2006-2008 Ion Gaztanaga] [id intrusive] [dirname intrusive] [purpose Intrusive containers] From b36ec05d0ae624db91f1c00a057902937b1e9482 Mon Sep 17 00:00:00 2001 From: Christopher Hite Date: Wed, 26 Aug 2009 08:59:34 +0000 Subject: [PATCH 12/29] merged sandbox-branches/intrusive_fix_SunCC (r55765 and r55775) fixing intrusive for Sun CC (#3339) [SVN r55784] --- include/boost/intrusive/detail/utilities.hpp | 8 +- include/boost/intrusive/hashtable.hpp | 4 +- test/smart_ptr.hpp | 104 +++++++++---------- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index ad81dc2..ab974ff 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -46,7 +46,7 @@ struct internal_base_hook_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; @@ -63,7 +63,7 @@ struct internal_any_hook_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; @@ -81,7 +81,7 @@ struct external_value_traits_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; @@ -92,7 +92,7 @@ struct external_bucket_traits_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index d8605aa..8f016f7 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -187,7 +187,7 @@ struct store_hash_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; @@ -204,7 +204,7 @@ struct optimize_multikey_bool struct two_or_three {one _[2 + Add];}; template static one test(...); template static two_or_three - test (detail::bool_* = 0); + test (int); static const std::size_t value = sizeof(test(0)); }; diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index dd945a8..70e4371 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -34,9 +34,9 @@ struct reinterpret_cast_tag {}; struct empty_type{}; template -struct random_it -: public boost::iterator +struct random_it +: public boost::iterator { typedef const T* const_pointer; typedef const T& const_reference; @@ -108,25 +108,25 @@ class smart_ptr public: //Public Functions //!Constructor from raw pointer (allows "0" pointer conversion). Never throws. - explicit smart_ptr(pointer ptr = 0) + smart_ptr(pointer ptr = 0) : m_ptr(ptr) {} //!Constructor from other pointer. Never throws. template - smart_ptr(T *ptr) + smart_ptr(T *ptr) : m_ptr(ptr) {} - //!Constructor from other smart_ptr + //!Constructor from other smart_ptr smart_ptr(const smart_ptr& ptr) : m_ptr(ptr.m_ptr) {} - //!Constructor from other smart_ptr. If pointers of pointee types are + //!Constructor from other smart_ptr. If pointers of pointee types are //!convertible, offset_ptrs will be convertibles. Never throws. template - smart_ptr(const smart_ptr &ptr) + smart_ptr(const smart_ptr &ptr) : m_ptr(ptr.m_ptr) {} @@ -159,16 +159,16 @@ class smart_ptr { return m_ptr; } //!Pointer-like -> operator. It can return 0 pointer. Never throws. - pointer operator->() const + pointer operator->() const { return this->get(); } - //!Dereferencing operator, if it is a null smart_ptr behavior + //!Dereferencing operator, if it is a null smart_ptr behavior //! is undefined. Never throws. - reference operator* () const + reference operator* () const { return *(this->get()); } //!Indexing operator. Never throws. - reference operator[](std::ptrdiff_t idx) const + reference operator[](std::ptrdiff_t idx) const { return this->get()[idx]; } //!Assignment from pointer (saves extra conversion). Never throws. @@ -179,18 +179,18 @@ class smart_ptr smart_ptr& operator= (const smart_ptr & pt) { m_ptr = pt.m_ptr; return *this; } - //!Assignment from related smart_ptr. If pointers of pointee types + //!Assignment from related smart_ptr. If pointers of pointee types //! are assignable, offset_ptrs will be assignable. Never throws. template smart_ptr& operator= (const smart_ptr & pt) { m_ptr = pt.m_ptr; return *this; } - + //!smart_ptr + std::ptrdiff_t. Never throws. - smart_ptr operator+ (std::ptrdiff_t offset) const + smart_ptr operator+ (std::ptrdiff_t offset) const { return smart_ptr(this->get()+offset); } //!smart_ptr - std::ptrdiff_t. Never throws. - smart_ptr operator- (std::ptrdiff_t offset) const + smart_ptr operator- (std::ptrdiff_t offset) const { return smart_ptr(this->get()-offset); } //!smart_ptr += std::ptrdiff_t. Never throws. @@ -202,7 +202,7 @@ class smart_ptr { m_ptr -= offset; return *this; } //!++smart_ptr. Never throws. - smart_ptr& operator++ (void) + smart_ptr& operator++ (void) { ++m_ptr; return *this; } //!smart_ptr++. Never throws. @@ -210,7 +210,7 @@ class smart_ptr { smart_ptr temp(*this); ++*this; return temp; } //!--smart_ptr. Never throws. - smart_ptr& operator-- (void) + smart_ptr& operator-- (void) { --m_ptr; return *this; } //!smart_ptr--. Never throws. @@ -218,16 +218,16 @@ class smart_ptr { smart_ptr temp(*this); --*this; return temp; } //!safe bool conversion operator. Never throws. - operator unspecified_bool_type() const + operator unspecified_bool_type() const { return this->get()? &self_t::unspecified_bool_type_func : 0; } - //!Not operator. Not needed in theory, but improves portability. + //!Not operator. Not needed in theory, but improves portability. //!Never throws. bool operator! () const { return this->get() == 0; } /* friend void swap (smart_ptr &pt, smart_ptr &pt2) - { + { value_type *ptr = pt.get(); pt = pt2; pt2 = ptr; @@ -237,67 +237,67 @@ class smart_ptr //!smart_ptr == smart_ptr. Never throws. template -inline bool operator== (const smart_ptr &pt1, +inline bool operator== (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() == pt2.get(); } //!smart_ptr != smart_ptr. Never throws. template -inline bool operator!= (const smart_ptr &pt1, +inline bool operator!= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() != pt2.get(); } //!smart_ptr < smart_ptr. Never throws. template -inline bool operator< (const smart_ptr &pt1, +inline bool operator< (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() < pt2.get(); } //!smart_ptr <= smart_ptr. Never throws. template -inline bool operator<= (const smart_ptr &pt1, +inline bool operator<= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() <= pt2.get(); } //!smart_ptr > smart_ptr. Never throws. template -inline bool operator> (const smart_ptr &pt1, +inline bool operator> (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() > pt2.get(); } //!smart_ptr >= smart_ptr. Never throws. template -inline bool operator>= (const smart_ptr &pt1, +inline bool operator>= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() >= pt2.get(); } -//!operator<< -template -inline std::basic_ostream & operator<< +//!operator<< +template +inline std::basic_ostream & operator<< (std::basic_ostream & os, smart_ptr const & p) { return os << p.get(); } -//!operator>> -template -inline std::basic_istream & operator>> +//!operator>> +template +inline std::basic_istream & operator>> (std::basic_istream & os, smart_ptr & p) { Y * tmp; return os >> tmp; p = tmp; } -//!std::ptrdiff_t + smart_ptr +//!std::ptrdiff_t + smart_ptr template inline smart_ptr operator+(std::ptrdiff_t diff, const smart_ptr& right) { return right + diff; } -//!smart_ptr - smart_ptr +//!smart_ptr - smart_ptr template inline std::ptrdiff_t operator- (const smart_ptr &pt, const smart_ptr &pt2) { return pt.get()- pt2.get(); } -//!swap specialization +//!swap specialization template -inline void swap (smart_ptr &pt, +inline void swap (smart_ptr &pt, smart_ptr &pt2) -{ +{ typename smart_ptr::value_type *ptr = pt.get(); pt = pt2; pt2 = ptr; @@ -310,35 +310,35 @@ inline T* get_pointer(const smart_ptr & p) { return p.get(); } //!Simulation of static_cast between pointers. Never throws. -template -inline smart_ptr +template +inline smart_ptr static_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::static_cast_tag()); +{ + return smart_ptr(r, detail::static_cast_tag()); } //!Simulation of const_cast between pointers. Never throws. -template +template inline smart_ptrconst_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::const_cast_tag()); +{ + return smart_ptr(r, detail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. Never throws. -template -inline smart_ptr +template +inline smart_ptr dynamic_pointer_cast(smart_ptr const & r) -{ +{ return smart_ptr - (r, detail::dynamic_cast_tag()); + (r, detail::dynamic_cast_tag()); } //!Simulation of reinterpret_cast between pointers. Never throws. -template +template inline smart_ptr reinterpret_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::reinterpret_cast_tag()); +{ + return smart_ptr(r, detail::reinterpret_cast_tag()); } } //namespace intrusive { From 8c6f93eae07abb1a00777372f3f5eb18bf297711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 14 Oct 2009 11:59:32 +0000 Subject: [PATCH 13/29] Fixes for 1.41 [SVN r56817] --- include/boost/intrusive/any_hook.hpp | 2 +- include/boost/intrusive/avl_set.hpp | 112 +++++++++- include/boost/intrusive/avl_set_hook.hpp | 4 +- include/boost/intrusive/avltree.hpp | 72 +++++- .../boost/intrusive/avltree_algorithms.hpp | 60 +++++ include/boost/intrusive/bs_set_hook.hpp | 4 +- .../intrusive/circular_list_algorithms.hpp | 4 +- .../intrusive/circular_slist_algorithms.hpp | 4 +- .../intrusive/derivation_value_traits.hpp | 2 +- .../detail/any_node_and_algorithms.hpp | 2 +- include/boost/intrusive/detail/assert.hpp | 2 +- .../detail/clear_on_destructor_base.hpp | 2 +- .../detail/common_slist_algorithms.hpp | 25 ++- .../boost/intrusive/detail/config_begin.hpp | 2 +- include/boost/intrusive/detail/config_end.hpp | 2 +- .../intrusive/detail/ebo_functor_holder.hpp | 5 +- .../intrusive/detail/function_detector.hpp | 87 ++++++++ .../boost/intrusive/detail/generic_hook.hpp | 2 +- .../boost/intrusive/detail/hashtable_node.hpp | 20 +- .../detail/is_stateful_value_traits.hpp | 56 +++++ include/boost/intrusive/detail/list_node.hpp | 18 +- include/boost/intrusive/detail/mpl.hpp | 5 +- .../intrusive/detail/parent_from_member.hpp | 2 +- .../boost/intrusive/detail/rbtree_node.hpp | 2 +- include/boost/intrusive/detail/slist_node.hpp | 18 +- .../intrusive/detail/transform_iterator.hpp | 2 +- .../intrusive/detail/tree_algorithms.hpp | 166 +++++++++----- include/boost/intrusive/detail/tree_node.hpp | 31 +-- include/boost/intrusive/detail/utilities.hpp | 150 +++++++------ include/boost/intrusive/detail/workaround.hpp | 2 +- include/boost/intrusive/hashtable.hpp | 78 +++---- include/boost/intrusive/intrusive_fwd.hpp | 2 +- .../intrusive/linear_slist_algorithms.hpp | 4 +- include/boost/intrusive/link_mode.hpp | 2 +- include/boost/intrusive/list.hpp | 5 +- include/boost/intrusive/list_hook.hpp | 4 +- .../boost/intrusive/member_value_traits.hpp | 2 +- include/boost/intrusive/options.hpp | 2 +- include/boost/intrusive/pointer_plus_bits.hpp | 4 +- include/boost/intrusive/priority_compare.hpp | 2 +- include/boost/intrusive/rbtree.hpp | 76 ++++++- include/boost/intrusive/rbtree_algorithms.hpp | 62 +++++- include/boost/intrusive/set.hpp | 107 ++++++++- include/boost/intrusive/set_hook.hpp | 4 +- include/boost/intrusive/sg_set.hpp | 111 ++++++++- include/boost/intrusive/sgtree.hpp | 87 +++++++- include/boost/intrusive/sgtree_algorithms.hpp | 70 ++++++ include/boost/intrusive/slist.hpp | 210 ++++++++++++++---- include/boost/intrusive/slist_hook.hpp | 4 +- include/boost/intrusive/splay_set.hpp | 4 +- include/boost/intrusive/splay_set_hook.hpp | 4 +- include/boost/intrusive/splaytree.hpp | 5 +- .../boost/intrusive/splaytree_algorithms.hpp | 99 ++++++++- include/boost/intrusive/treap.hpp | 187 +++++++++++----- include/boost/intrusive/treap_algorithms.hpp | 165 +++++++++++--- include/boost/intrusive/treap_set.hpp | 207 ++++++++++++++--- .../boost/intrusive/trivial_value_traits.hpp | 2 +- include/boost/intrusive/unordered_set.hpp | 49 ++-- .../boost/intrusive/unordered_set_hook.hpp | 4 +- 59 files changed, 1956 insertions(+), 471 deletions(-) create mode 100644 include/boost/intrusive/detail/function_detector.hpp create mode 100644 include/boost/intrusive/detail/is_stateful_value_traits.hpp diff --git a/include/boost/intrusive/any_hook.hpp b/include/boost/intrusive/any_hook.hpp index 29a5b08..b1b0194 100644 --- a/include/boost/intrusive/any_hook.hpp +++ b/include/boost/intrusive/any_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index 3998f05..a944077 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -489,6 +489,60 @@ class avl_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1532,9 +1586,63 @@ class avl_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! - //! Complexity: Average complexity is constant time. + //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! diff --git a/include/boost/intrusive/avl_set_hook.hpp b/include/boost/intrusive/avl_set_hook.hpp index 00d2fc8..23b1f0b 100644 --- a/include/boost/intrusive/avl_set_hook.hpp +++ b/include/boost/intrusive/avl_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class avl_set_base_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -221,6 +222,7 @@ class avl_set_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index c247e32..e65f182 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -704,6 +704,76 @@ class avltree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index 6385ff9..a632581 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -530,6 +530,66 @@ class avltree_algorithms return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + rebalance_after_insertion(header, new_node); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + rebalance_after_insertion(header, new_node); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/bs_set_hook.hpp b/include/boost/intrusive/bs_set_hook.hpp index 3ab0310..bf8e2de 100644 --- a/include/boost/intrusive/bs_set_hook.hpp +++ b/include/boost/intrusive/bs_set_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class bs_set_base_hook { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -220,6 +221,7 @@ class bs_set_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/circular_list_algorithms.hpp b/include/boost/intrusive/circular_list_algorithms.hpp index aeb0358..16b1971 100644 --- a/include/boost/intrusive/circular_list_algorithms.hpp +++ b/include/boost/intrusive/circular_list_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -110,7 +110,7 @@ class circular_list_algorithms //! Effects: Returns the number of nodes in a circular list. If the circular list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index cb9cb3b..ae06396 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -199,7 +199,7 @@ class circular_slist_algorithms //! Effects: Returns the number of nodes in a circular list. If the circular list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 58467d5..88edeab 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp index 6a3d955..e2fbbfa 100644 --- a/include/boost/intrusive/detail/any_node_and_algorithms.hpp +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/assert.hpp b/include/boost/intrusive/detail/assert.hpp index 0fe98f8..cfe392b 100644 --- a/include/boost/intrusive/detail/assert.hpp +++ b/include/boost/intrusive/detail/assert.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/clear_on_destructor_base.hpp b/include/boost/intrusive/detail/clear_on_destructor_base.hpp index 838dd67..6765dfa 100644 --- a/include/boost/intrusive/detail/clear_on_destructor_base.hpp +++ b/include/boost/intrusive/detail/clear_on_destructor_base.hpp @@ -1,6 +1,6 @@ //////} // /////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2009. 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) // diff --git a/include/boost/intrusive/detail/common_slist_algorithms.hpp b/include/boost/intrusive/detail/common_slist_algorithms.hpp index d837ad0..c6bdb20 100644 --- a/include/boost/intrusive/detail/common_slist_algorithms.hpp +++ b/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -74,15 +74,22 @@ class common_slist_algorithms NodeTraits::set_next(prev_node, this_node); } - static void transfer_after(node_ptr p, node_ptr b, node_ptr e) + static void incorporate_after(node_ptr bp, node_ptr b, node_ptr be) { - if (p != b && p != e && b != e) { - node_ptr next_b = NodeTraits::get_next(b); - node_ptr next_e = NodeTraits::get_next(e); - node_ptr next_p = NodeTraits::get_next(p); - NodeTraits::set_next(b, next_e); - NodeTraits::set_next(e, next_p); - NodeTraits::set_next(p, next_b); + node_ptr p(NodeTraits::get_next(bp)); + NodeTraits::set_next(bp, b); + NodeTraits::set_next(be, p); + } + + static void transfer_after(node_ptr bp, node_ptr bb, node_ptr be) + { + if (bp != bb && bp != be && bb != be) { + node_ptr next_b = NodeTraits::get_next(bb); + node_ptr next_e = NodeTraits::get_next(be); + node_ptr next_p = NodeTraits::get_next(bp); + NodeTraits::set_next(bb, next_e); + NodeTraits::set_next(be, next_p); + NodeTraits::set_next(bp, next_b); } } }; diff --git a/include/boost/intrusive/detail/config_begin.hpp b/include/boost/intrusive/detail/config_begin.hpp index 1c390be..bb126fc 100644 --- a/include/boost/intrusive/detail/config_begin.hpp +++ b/include/boost/intrusive/detail/config_begin.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/config_end.hpp b/include/boost/intrusive/detail/config_end.hpp index f04b2e9..4277cb5 100644 --- a/include/boost/intrusive/detail/config_end.hpp +++ b/include/boost/intrusive/detail/config_end.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/ebo_functor_holder.hpp b/include/boost/intrusive/detail/ebo_functor_holder.hpp index 35628f2..d4c2d15 100644 --- a/include/boost/intrusive/detail/ebo_functor_holder.hpp +++ b/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Joaquin M Lopez Munoz 2006-2008 +// (C) Copyright Joaquin M Lopez Munoz 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP #define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP +#include #include namespace boost { @@ -89,4 +90,6 @@ class ebo_functor_holder } //namespace intrusive { } //namespace boost { +#include + #endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP diff --git a/include/boost/intrusive/detail/function_detector.hpp b/include/boost/intrusive/detail/function_detector.hpp new file mode 100644 index 0000000..a20db6d --- /dev/null +++ b/include/boost/intrusive/detail/function_detector.hpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2009. +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// This code was modified from the code posted by Alexandre Courpron in his +// article "Interface Detection" in The Code Project: +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2007 Alexandre Courpron +// +// Permission to use, copy, modify, redistribute and sell this software, +// provided that this copyright notice appears on all copies of the software. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP +#define BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP + +#include + +namespace boost { +namespace intrusive { +namespace function_detector { + + typedef char NotFoundType; + struct StaticFunctionType { NotFoundType x [2]; }; + struct NonStaticFunctionType { NotFoundType x [3]; }; + + enum + { NotFound = 0, + StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ), + NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType ) + }; + +} //namespace boost { +} //namespace intrusive { +} //namespace function_detector { + +#define BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \ + namespace boost { \ + namespace intrusive { \ + namespace function_detector { \ + template < class T, \ + class NonStaticType, \ + class NonStaticConstType, \ + class StaticType > \ + class DetectMember_##InstantiationKey_##Identifier { \ + template < NonStaticType > \ + struct TestNonStaticNonConst ; \ + \ + template < NonStaticConstType > \ + struct TestNonStaticConst ; \ + \ + template < StaticType > \ + struct TestStatic ; \ + \ + template \ + static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \ + \ + template \ + static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \ + \ + template \ + static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \ + \ + template \ + static NotFoundType Test( ... ); \ + public : \ + static const int check = NotFound + (sizeof(Test(0, 0)) - sizeof(NotFoundType));\ + };\ +}}} //namespace boost::intrusive::function_detector { + +#define BOOST_INTRUSIVE_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \ + ::boost::intrusive::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\ + ReturnType (Class::*)Params,\ + ReturnType (Class::*)Params const,\ + ReturnType (*)Params \ + >::check + +#include + +#endif //@ifndef BOOST_INTRUSIVE_DETAIL_FUNCTION_DETECTOR_HPP diff --git a/include/boost/intrusive/detail/generic_hook.hpp b/include/boost/intrusive/detail/generic_hook.hpp index 1b4736b..ae1282e 100644 --- a/include/boost/intrusive/detail/generic_hook.hpp +++ b/include/boost/intrusive/detail/generic_hook.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index fbb150d..1676b1c 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -100,8 +100,12 @@ template class hashtable_iterator : public std::iterator < std::forward_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { typedef typename Container::real_value_traits real_value_traits; @@ -116,8 +120,11 @@ class hashtable_iterator { return typename Container::node_ptr(&static_cast(*p)); } public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - ::type value_type; + ::type &reference; hashtable_iterator () {} @@ -133,6 +140,9 @@ class hashtable_iterator const siterator &slist_it() const { return slist_it_; } + hashtable_iterator unconst() const + { return hashtable_iterator(this->slist_it(), this->get_container()); } + public: hashtable_iterator& operator++() { this->increment(); return *this; } @@ -150,10 +160,10 @@ class hashtable_iterator friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2) { return !(i == i2); } - value_type& operator*() const + reference operator*() const { return *this->operator ->(); } - value_type* operator->() const + pointer operator->() const { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } const Container *get_container() const diff --git a/include/boost/intrusive/detail/is_stateful_value_traits.hpp b/include/boost/intrusive/detail/is_stateful_value_traits.hpp new file mode 100644 index 0000000..a11f988 --- /dev/null +++ b/include/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2009. +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP +#define BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP + +#include +#include + +BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_node_ptr, boost_intrusive) +BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_value_ptr, boost_intrusive) + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct is_stateful_value_traits +{ + typedef typename ValueTraits::node_ptr node_ptr; + typedef typename ValueTraits::pointer pointer; + typedef typename ValueTraits::value_type value_type; + typedef typename ValueTraits::const_node_ptr const_node_ptr; + typedef typename ValueTraits::const_pointer const_pointer; + + typedef ValueTraits value_traits; + + static const bool value = + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, node_ptr, to_node_ptr, (value_type&) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, pointer, to_value_ptr, (node_ptr) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_node_ptr, to_node_ptr, (const value_type&) ))) + || + (boost::intrusive::function_detector::NonStaticFunction == + (BOOST_INTRUSIVE_DETECT_FUNCTION(ValueTraits, boost_intrusive, const_pointer, to_value_ptr, (const_node_ptr) ))) + ; +}; + +}}} + +#include + +#endif //@ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index effd36a..935c522 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -63,8 +63,12 @@ template class list_iterator : public std::iterator < std::bidirectional_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -78,11 +82,11 @@ class list_iterator detail::store_cont_ptr_on_it::value; public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; list_iterator() : members_ (node_ptr(0), 0) @@ -135,7 +139,7 @@ class list_iterator bool operator!= (const list_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const diff --git a/include/boost/intrusive/detail/mpl.hpp b/include/boost/intrusive/detail/mpl.hpp index 20f50da..5f57e37 100644 --- a/include/boost/intrusive/detail/mpl.hpp +++ b/include/boost/intrusive/detail/mpl.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,7 @@ #ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP #define BOOST_INTRUSIVE_DETAIL_MPL_HPP +#include #include namespace boost { @@ -364,4 +365,6 @@ struct ls_zeros<1> } //namespace intrusive } //namespace boost +#include + #endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index c750ad8..0b30867 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/rbtree_node.hpp b/include/boost/intrusive/detail/rbtree_node.hpp index 6d6dd84..87ba59d 100644 --- a/include/boost/intrusive/detail/rbtree_node.hpp +++ b/include/boost/intrusive/detail/rbtree_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index 4101092..a7df9e1 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -55,8 +55,12 @@ template class slist_iterator : public std::iterator < std::forward_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -70,11 +74,11 @@ class slist_iterator detail::store_cont_ptr_on_it::value; public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; slist_iterator() : members_ (node_ptr(0), 0) @@ -114,7 +118,7 @@ class slist_iterator bool operator!= (const slist_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index a4afd77..a9de49e 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 57d5206..32bbfb5 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -160,7 +160,7 @@ class tree_algorithms //! //! Throws: Nothing. static bool unique(const_node_ptr node) - { return NodeTraits::get_parent(node) == 0; } + { return !NodeTraits::get_parent(node); } static node_ptr get_header(const_node_ptr node) { @@ -460,7 +460,8 @@ class tree_algorithms static node_ptr prev_node(node_ptr p) { if(is_header(p)){ - return maximum(NodeTraits::get_parent(p)); + return NodeTraits::get_right(p); + //return maximum(NodeTraits::get_parent(p)); } else if(NodeTraits::get_left(p)){ return maximum(NodeTraits::get_left(p)); @@ -721,21 +722,19 @@ class tree_algorithms static bool is_header(const_node_ptr p) { - bool is_header = false; - if(NodeTraits::get_parent(p) == p){ - is_header = true; + node_ptr p_left (NodeTraits::get_left(p)); + node_ptr p_right(NodeTraits::get_right(p)); + if(!NodeTraits::get_parent(p) || //Header condition when empty tree + (p_left && p_right && //Header always has leftmost and rightmost + (p_left == p_right || //Header condition when only node + (NodeTraits::get_parent(p_left) != p || + NodeTraits::get_parent(p_right) != p )) + //When tree size > 1 headers can't be leftmost's + //and rightmost's parent + )){ + return true; } - else if(NodeTraits::get_parent(NodeTraits::get_parent(p)) == p){ - if(NodeTraits::get_left(p) != 0){ - if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ - is_header = true; - } - if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ - is_header = true; - } - } - } - return is_header; + return false; } //! Requires: "header" must be the header node of a tree. @@ -894,10 +893,32 @@ class tree_algorithms //! erased between the "insert_check" and "insert_commit" calls. static void insert_unique_commit (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { return insert_commit(header, new_value, commit_data); } + + static void insert_commit + (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) { //Check if commit_data has not been initialized by a insert_unique_check call. BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != 0); - link(header, new_value, commit_data.node, commit_data.link_left); + node_ptr parent_node(commit_data.node); + if(parent_node == header){ + NodeTraits::set_parent(header, new_node); + NodeTraits::set_right(header, new_node); + NodeTraits::set_left(header, new_node); + } + else if(commit_data.link_left){ + NodeTraits::set_left(parent_node, new_node); + if(parent_node == NodeTraits::get_left(header)) + NodeTraits::set_left(header, new_node); + } + else{ + NodeTraits::set_right(parent_node, new_node); + if(parent_node == NodeTraits::get_right(header)) + NodeTraits::set_right(header, new_node); + } + NodeTraits::set_parent(new_node, parent_node); + NodeTraits::set_right(new_node, node_ptr(0)); + NodeTraits::set_left(new_node, node_ptr(0)); } //! Requires: "header" must be the header node of a tree. @@ -979,9 +1000,9 @@ class tree_algorithms { //hint must be bigger than the key if(hint == header || comp(key, hint)){ - node_ptr prev = hint; - //The previous value should be less than the key - if(prev == NodeTraits::get_left(header) || comp((prev = prev_node(hint)), key)){ + node_ptr prev(hint); + //Previous value should be less than the key + if(hint == begin_node(header)|| comp((prev = prev_node(hint)), key)){ commit_data.link_left = unique(header) || !NodeTraits::get_left(hint); commit_data.node = commit_data.link_left ? hint : prev; if(pdepth){ @@ -989,14 +1010,9 @@ class tree_algorithms } return std::pair(node_ptr(), true); } - else{ - return insert_unique_check(header, key, comp, commit_data, pdepth); - } - } - //The hint was wrong, use hintless insert - else{ - return insert_unique_check(header, key, comp, commit_data, pdepth); } + //Hint was wrong, use hintless insertion + return insert_unique_check(header, key, comp, commit_data, pdepth); } template @@ -1040,7 +1056,7 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_check(h, hint, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } @@ -1050,7 +1066,7 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } @@ -1060,10 +1076,72 @@ class tree_algorithms { insert_commit_data commit_data; insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth); - link(h, new_node, commit_data.node, commit_data.link_left); + insert_commit(h, new_node, commit_data); return new_node; } + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + insert_before_check(header, pos, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + return new_node; + } + + static void insert_before_check + ( node_ptr header, node_ptr pos + , insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr prev(pos); + if(pos != NodeTraits::get_left(header)) + prev = prev_node(pos); + bool link_left = unique(header) || !NodeTraits::get_left(pos); + commit_data.link_left = link_left; + commit_data.node = link_left ? pos : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } + } + + static void push_back + (node_ptr header, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + push_back_check(header, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + } + + static void push_back_check + (node_ptr header, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr prev(NodeTraits::get_right(header)); + if(pdepth){ + *pdepth = prev == header ? 0 : depth(prev) + 1; + } + commit_data.link_left = false; + commit_data.node = prev; + } + + static void push_front + (node_ptr header, node_ptr new_node, std::size_t *pdepth = 0) + { + insert_commit_data commit_data; + push_front_check(header, commit_data, pdepth); + insert_commit(header, new_node, commit_data); + } + + static void push_front_check + (node_ptr header, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + node_ptr pos(NodeTraits::get_left(header)); + if(pdepth){ + *pdepth = pos == header ? 0 : depth(pos) + 1; + } + commit_data.link_left = true; + commit_data.node = pos; + } + //! Requires: p can't be a header node. //! //! Effects: Calculates the depth of a node: the depth of a @@ -1303,32 +1381,10 @@ class tree_algorithms replace_own_impl(p, x, header, p_old_parent, p_was_left); } - static void link(node_ptr header, node_ptr z, node_ptr par, bool left) - { - if(par == header){ - NodeTraits::set_parent(header, z); - NodeTraits::set_right(header, z); - NodeTraits::set_left(header, z); - } - else if(left){ - NodeTraits::set_left(par, z); - if(par == NodeTraits::get_left(header)) - NodeTraits::set_left(header, z); - } - else{ - NodeTraits::set_right(par, z); - if(par == NodeTraits::get_right(header)) - NodeTraits::set_right(header, z); - } - NodeTraits::set_parent(z, par); - NodeTraits::set_right(z, node_ptr(0)); - NodeTraits::set_left(z, node_ptr(0)); - } - static void erase(node_ptr header, node_ptr z) { data_for_rebalance ignored; - erase(header, z, nop_erase_fixup(), ignored); + erase_impl(header, z, ignored); } struct data_for_rebalance @@ -1609,12 +1665,12 @@ class tree_algorithms NodeTraits::set_parent(x, x_parent); tree_algorithms::replace_own (z, x, header); if(NodeTraits::get_left(header) == z){ - NodeTraits::set_left(header, NodeTraits::get_right(z) == 0 ? // z->get_left() must be null also + NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also NodeTraits::get_parent(z) : // makes leftmost == header if z == root tree_algorithms::minimum (x)); } if(NodeTraits::get_right(header) == z){ - NodeTraits::set_right(header, NodeTraits::get_left(z) == 0 ? // z->get_right() must be null also + NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also NodeTraits::get_parent(z) : // makes rightmost == header if z == root tree_algorithms::maximum(x)); } diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index 146f758..3508e85 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -72,8 +72,12 @@ template class tree_iterator : public std::iterator < std::bidirectional_iterator_tag + , typename Container::value_type + , typename std::iterator_traits::difference_type , typename detail::add_const_if_c - ::type + ::type * + , typename detail::add_const_if_c + ::type & > { protected: @@ -88,12 +92,11 @@ class tree_iterator detail::store_cont_ptr_on_it::value; public: - public: + typedef typename Container::value_type value_type; + typedef typename detail::add_const_if_c + ::type *pointer; typedef typename detail::add_const_if_c - - ::type value_type; - typedef value_type & reference; - typedef value_type * pointer; + ::type &reference; tree_iterator() : members_ (0, 0) @@ -146,27 +149,17 @@ class tree_iterator bool operator!= (const tree_iterator& i) const { return !operator== (i); } - value_type& operator*() const + reference operator*() const { return *operator->(); } pointer operator->() const { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } const Container *get_container() const - { - if(store_container_ptr) - return static_cast(members_.get_ptr()); - else - return 0; - } + { return static_cast(members_.get_ptr()); } const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } + { return &this->get_container()->get_real_value_traits(); } tree_iterator end_iterator_from_it() const { diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index ab974ff..7846716 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -45,8 +46,7 @@ struct internal_base_hook_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -62,8 +62,7 @@ struct internal_any_hook_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -80,8 +79,7 @@ struct external_value_traits_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -91,8 +89,7 @@ struct external_bucket_traits_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -337,16 +334,6 @@ struct select_constptr >::type type; }; -template -struct store_cont_ptr_on_it -{ - typedef typename Container::value_traits value_traits; - static const bool value = - !detail::is_empty_class::value - || detail::external_value_traits_is_true::value - ; -}; - template struct add_const_if_c { @@ -357,58 +344,6 @@ struct add_const_if_c >::type type; }; -template -struct node_to_value - : public detail::select_constptr - < typename boost::pointer_to_other - ::type - , detail::store_cont_ptr_on_it::value - >::type -{ - static const bool store_container_ptr = - detail::store_cont_ptr_on_it::value; - - typedef typename Container::real_value_traits real_value_traits; - typedef typename real_value_traits::value_type value_type; - typedef typename detail::select_constptr - < typename boost::pointer_to_other - ::type - , store_container_ptr >::type Base; - typedef typename real_value_traits::node_traits::node node; - typedef typename detail::add_const_if_c - ::type vtype; - typedef typename detail::add_const_if_c - ::type ntype; - typedef typename boost::pointer_to_other - ::type npointer; - - node_to_value(const Container *cont) - : Base(cont) - {} - - typedef vtype & result_type; - typedef ntype & first_argument_type; - - const Container *get_container() const - { - if(store_container_ptr) - return static_cast(Base::get_ptr()); - else - return 0; - } - - const real_value_traits *get_real_value_traits() const - { - if(store_container_ptr) - return &this->get_container()->get_real_value_traits(); - else - return 0; - } - - result_type operator()(first_argument_type arg) const - { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } -}; - template struct link_dispatch {}; @@ -625,6 +560,79 @@ class exception_array_disposer } }; +template +struct store_cont_ptr_on_it_impl +{ + static const bool value = is_stateful_value_traits::value; +}; + +template +struct store_cont_ptr_on_it_impl +{ + static const bool value = false; +}; + +template +struct store_cont_ptr_on_it +{ + typedef typename Container::value_traits value_traits; + static const bool value = store_cont_ptr_on_it_impl + ::value>::value; +}; + +template +struct node_to_value + : public detail::select_constptr + < typename boost::pointer_to_other + ::type + , detail::store_cont_ptr_on_it::value + >::type +{ + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::value_type value_type; + typedef typename detail::select_constptr + < typename boost::pointer_to_other + ::type + , store_container_ptr >::type Base; + typedef typename real_value_traits::node_traits::node node; + typedef typename detail::add_const_if_c + ::type vtype; + typedef typename detail::add_const_if_c + ::type ntype; + typedef typename boost::pointer_to_other + ::type npointer; + + node_to_value(const Container *cont) + : Base(cont) + {} + + typedef vtype & result_type; + typedef ntype & first_argument_type; + + const Container *get_container() const + { + if(store_container_ptr) + return static_cast(Base::get_ptr()); + else + return 0; + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + result_type operator()(first_argument_type arg) const + { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } +}; + + } //namespace detail } //namespace intrusive } //namespace boost diff --git a/include/boost/intrusive/detail/workaround.hpp b/include/boost/intrusive/detail/workaround.hpp index a4c0974..dd70862 100644 --- a/include/boost/intrusive/detail/workaround.hpp +++ b/include/boost/intrusive/detail/workaround.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2009. 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) // diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 8f016f7..51cc6c1 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -186,8 +186,7 @@ struct store_hash_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -203,8 +202,7 @@ struct optimize_multikey_bool template struct two_or_three {one _[2 + Add];}; template static one test(...); - template static two_or_three - test (int); + template static two_or_three test (int); static const std::size_t value = sizeof(test(0)); }; @@ -603,7 +601,7 @@ class hashtable_impl typedef typename real_value_traits::pointer pointer; typedef typename real_value_traits::const_pointer const_pointer; - typedef typename std::iterator_traits::value_type value_type; + typedef typename real_value_traits::value_type value_type; typedef typename std::iterator_traits::reference reference; typedef typename std::iterator_traits::reference const_reference; typedef typename std::iterator_traits::difference_type difference_type; @@ -626,7 +624,7 @@ class hashtable_impl ::type const_node_ptr; typedef typename slist_impl::node_algorithms node_algorithms; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool store_hash = detail::store_hash_is_true::value; static const bool unique_keys = 0 != (Config::bool_flags & detail::hash_bool_flags::unique_keys_pos); @@ -1231,8 +1229,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { this->erase_and_dispose(i, detail::null_disposer()); } + iterator erase(const_iterator i) + { return this->erase_and_dispose(i, detail::null_disposer()); } //! Effects: Erases the range pointed to by b end e. //! @@ -1243,8 +1241,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { this->erase_and_dispose(b, e, detail::null_disposer()); } + iterator erase(const_iterator b, const_iterator e) + { return this->erase_and_dispose(b, e, detail::null_disposer()); } //! Effects: Erases all the elements with the given value. //! @@ -1297,19 +1295,20 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) { + iterator ret(i.unconst()); + ++ret; priv_erase(i, disposer, optimize_multikey_t()); this->priv_size_traits().decrement(); priv_erasure_update_cache(); + return ret; } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases the range pointed to by b end e. @@ -1323,31 +1322,32 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { - if(b == e) return; + if(b != e){ + //Get the bucket number and local iterator for both iterators + siterator first_local_it(b.slist_it()); + size_type first_bucket_num = this->priv_get_bucket_num(first_local_it); - //Get the bucket number and local iterator for both iterators - siterator first_local_it(b.slist_it()); - size_type first_bucket_num = this->priv_get_bucket_num(first_local_it); + siterator before_first_local_it + = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it); + size_type last_bucket_num; + siterator last_local_it; - siterator before_first_local_it - = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it); - size_type last_bucket_num; - siterator last_local_it; - - //For the end iterator, we will assign the end iterator - //of the last bucket - if(e == this->end()){ - last_bucket_num = this->bucket_count() - 1; - last_local_it = priv_buckets()[last_bucket_num].end(); + //For the end iterator, we will assign the end iterator + //of the last bucket + if(e == this->end()){ + last_bucket_num = this->bucket_count() - 1; + last_local_it = priv_buckets()[last_bucket_num].end(); + } + else{ + last_local_it = e.slist_it(); + last_bucket_num = this->priv_get_bucket_num(last_local_it); + } + priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); + priv_erasure_update_cache(first_bucket_num, last_bucket_num); } - else{ - last_local_it = e.slist_it(); - last_bucket_num = this->priv_get_bucket_num(last_local_it); - } - priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); - priv_erasure_update_cache(first_bucket_num, last_bucket_num); + return e.unconst(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 5b1e451..7c9b2a1 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/linear_slist_algorithms.hpp b/include/boost/intrusive/linear_slist_algorithms.hpp index 9d045a5..193b449 100644 --- a/include/boost/intrusive/linear_slist_algorithms.hpp +++ b/include/boost/intrusive/linear_slist_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -156,7 +156,7 @@ class linear_slist_algorithms //! Effects: Returns the number of nodes in a linear list. If the linear list //! is empty, returns 1. //! - //! Complexity: Constant + //! Complexity: Linear //! //! Throws: Nothing. static std::size_t count(const_node_ptr this_node) diff --git a/include/boost/intrusive/link_mode.hpp b/include/boost/intrusive/link_mode.hpp index 16b9649..17012c9 100644 --- a/include/boost/intrusive/link_mode.hpp +++ b/include/boost/intrusive/link_mode.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index d38d960..2cf3fed 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -106,7 +106,8 @@ class list_impl typedef circular_list_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::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + BOOST_STATIC_ASSERT(( stateful_value_traits == false )); /// @cond diff --git a/include/boost/intrusive/list_hook.hpp b/include/boost/intrusive/list_hook.hpp index 2deceb0..ed93434 100644 --- a/include/boost/intrusive/list_hook.hpp +++ b/include/boost/intrusive/list_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -93,6 +93,7 @@ class list_base_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -214,6 +215,7 @@ class list_member_hook ::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index 372334c..ce7e56b 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index 8ab0890..d692b1e 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/pointer_plus_bits.hpp b/include/boost/intrusive/pointer_plus_bits.hpp index b2b51e8..10b2fe0 100644 --- a/include/boost/intrusive/pointer_plus_bits.hpp +++ b/include/boost/intrusive/pointer_plus_bits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -50,7 +50,7 @@ template struct pointer_plus_bits; //!This is the specialization to embed extra bits of information -//!in a raw pointer. The extra bits are stored in the lower bit of the pointer. +//!in a raw pointer. The extra bits are stored in the lower bits of the pointer. template struct pointer_plus_bits { diff --git a/include/boost/intrusive/priority_compare.hpp b/include/boost/intrusive/priority_compare.hpp index 9689851..abde27a 100644 --- a/include/boost/intrusive/priority_compare.hpp +++ b/include/boost/intrusive/priority_compare.hpp @@ -23,7 +23,7 @@ namespace intrusive { template struct priority_compare - : public std::binary_function + : public std::binary_function { bool operator()(const T &val, const T &val2) const { diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 572b545..8d9cacf 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -116,8 +117,7 @@ class rbtree_impl typedef rbtree_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::value; - + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: typedef detail::size_holder size_traits; @@ -704,6 +704,76 @@ class rbtree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 37140a3..ca6f7eb 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -585,6 +585,66 @@ class rbtree_algorithms return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + rebalance_after_insertion(header, new_node); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + rebalance_after_insertion(header, new_node); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 40d7c6b..54c5a65 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -490,6 +490,60 @@ class set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1533,6 +1587,57 @@ class multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. diff --git a/include/boost/intrusive/set_hook.hpp b/include/boost/intrusive/set_hook.hpp index 1420480..35746a2 100644 --- a/include/boost/intrusive/set_hook.hpp +++ b/include/boost/intrusive/set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -98,6 +98,7 @@ class set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -224,6 +225,7 @@ class set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/sg_set.hpp b/include/boost/intrusive/sg_set.hpp index 4c519c1..3a7c77a 100644 --- a/include/boost/intrusive/sg_set.hpp +++ b/include/boost/intrusive/sg_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -381,7 +381,7 @@ class sg_set_impl //! Requires: key_value_comp must be a comparison function that induces //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! key_value_comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the sg_set, using //! a user provided key instead of the value itself. @@ -416,7 +416,7 @@ class sg_set_impl //! Requires: key_value_comp must be a comparison function that induces //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! key_value_comp compares an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the sg_set, using //! a user provided key instead of the value itself, using "hint" @@ -489,6 +489,60 @@ class sg_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" or "value" is not unique tree ordering and uniqueness + //! invariants will be broken respectively. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than or equal to the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than or equal to the the mimum inserted key tree ordering or uniqueness + //! invariants will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. @@ -1572,6 +1626,57 @@ class sg_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 0d19919..5507893 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -244,7 +244,7 @@ class sgtree_impl static const bool floating_point = Config::floating_point; static const bool constant_time_size = true; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -871,6 +871,88 @@ class sgtree_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the tree before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" tree ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_ptr p = node_algorithms::insert_before + ( node_ptr(&priv_header()), pos.pointed_node(), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the tree in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_algorithms::push_back + ( node_ptr(&priv_header()), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the tree in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key tree ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_algorithms::push_front + ( node_ptr(&priv_header()), to_insert + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. @@ -1071,7 +1153,6 @@ class sgtree_impl { node_algorithms::clear_and_dispose(node_ptr(&priv_header()) , detail::node_disposer(disposer, this)); - node_algorithms::init_header(&priv_header()); this->priv_size_traits().set_size(0); } diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index c9af84f..bb6ef06 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -539,6 +539,76 @@ class sgtree_algorithms return ret; } + + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + template + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::insert_before(header, pos, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_back(node_ptr header, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::push_back(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_front(node_ptr header, node_ptr new_node + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::push_front(header, new_node, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index e430fb1..8314a75 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -140,7 +140,7 @@ class slist_impl >::type node_algorithms; static const bool constant_time_size = Config::constant_time_size; - static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; static const bool linear = Config::linear; static const bool cache_last = Config::cache_last; @@ -539,6 +539,36 @@ class slist_impl const_iterator cbefore_begin() const { return this->before_begin(); } + //! Effects: Returns an iterator to the last element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + iterator last() + { return iterator (this->get_last_node(), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + const_iterator last() const + { return const_iterator (this->get_last_node(), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: This function is present only if cached_last<> option is true. + const_iterator clast() const + { return const_iterator(this->get_last_node(), this); } + //! Precondition: end_iterator must be a valid end iterator //! of slist. //! @@ -1058,20 +1088,31 @@ class slist_impl //! Effects: Transfers all the elements of list x to this list, after the //! the element pointed by prev. No destructors or copy constructors are called. //! - //! Returns: The last element inserted of x or prev if x is empty. - //! This iterator can be used as new "prev" iterator for a new splice_after call. - //! that will splice new values after the previously spliced values. + //! Returns: Nothing. //! //! Throws: Nothing. //! - //! Complexity: Linear to the elements contained in x. - //! Constant-time if cache_last<> option is true. + //! Complexity: In general, linear to the elements contained in x. + //! Constant-time if cache_last<> option is true and also constant-time if + //! linear<> option is true "this" is empty and "last" is not used. //! //! Note: 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(const_iterator prev, slist_impl &x) + //! + //! Additional note: If the optional parameter "last" is provided, it will be + //! assigned to the last spliced element or prev if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice_after call. + //! that will splice new values after the previously spliced values. + void splice_after(const_iterator prev, slist_impl &x, const_iterator *last = 0) { - if (!x.empty()){ + if(x.empty()){ + if(last) *last = prev; + } + else if(linear && this->empty()){ + this->swap(x); + if(last) *last = this->previous(this->cend()); + } + else{ 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()); @@ -1084,10 +1125,7 @@ class slist_impl 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.unconst(); - } - else{ - return prev.unconst(); + if(last) *last = last_x; } } @@ -1166,10 +1204,7 @@ class slist_impl //! Effects: Transfers all the elements of list x to this list, before the //! the element pointed by it. No destructors or copy constructors are called. //! - //! Returns: The last element inserted of x or the previous element - //! of it if x is empty. - //! This iterator can be used as new "prev" iterator for a new splice call. - //! that will splice new values after the previously spliced values. + //! Returns: Nothing. //! //! Throws: Nothing. //! @@ -1180,8 +1215,13 @@ class slist_impl //! //! Note: 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(const_iterator it, slist_impl &x) - { return this->splice_after(this->previous(it), x); } + //! + //! Additional note: If the optional parameter "last" is provided, it will be + //! assigned to the last spliced element or prev if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice_after call. + //! that will splice new values after the previously spliced values. + void splice(const_iterator it, slist_impl &x, iterator *last = 0) + { this->splice_after(this->previous(it), x, last); } //! Requires: it p must be a valid iterator of *this. //! elem must point to an element contained in list @@ -1254,7 +1294,7 @@ class slist_impl void sort(Predicate p) { if (node_traits::get_next(node_traits::get_next(this->get_root_node())) - != this->get_root_node()) { + != this->get_root_node()) { slist_impl carry; slist_impl counter[64]; int fill = 0; @@ -1265,33 +1305,28 @@ class slist_impl int i = 0; while(i < fill && !counter[i].empty()) { carry.swap(counter[i]); - last_inserted = carry.merge(counter[i++], p); + carry.merge(counter[i++], p, &last_inserted); } BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty()); + const_iterator last_element(carry.previous(last_inserted, carry.end())); - node_ptr p = node_algorithms::get_previous_node - (last_inserted.pointed_node(), carry.cend().pointed_node()); - const_iterator last_element(p, this); if(constant_time_size){ counter[i].splice_after( counter[i].cbefore_begin(), carry - , carry.cbefore_begin(), last_element - , carry.size()); + , carry.cbefore_begin(), last_element + , carry.size()); } else{ counter[i].splice_after( counter[i].cbefore_begin(), carry - , carry.cbefore_begin(), last_element); + , carry.cbefore_begin(), last_element); } if(i == fill) ++fill; } for (int i = 1; i < fill; ++i) - last_inserted = counter[i].merge(counter[i-1], p); - BOOST_INTRUSIVE_INVARIANT_ASSERT(this->empty()); - - node_ptr p = node_algorithms::get_previous_node - (last_inserted.pointed_node(), counter[--fill].end().pointed_node()); - const_iterator last_element(p, this); + counter[i].merge(counter[i-1], p, &last_inserted); + --fill; + const_iterator last_element(counter[fill].previous(last_inserted, counter[fill].end())); if(constant_time_size){ this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin() , last_element, counter[fill].size()); @@ -1330,7 +1365,7 @@ class slist_impl //! in order into *this. The merge is stable; that is, if an element from *this is //! equivalent to one from x, then the element from *this will precede the one from x. //! - //! Returns: An iterator to the last transferred value, end() is x is empty. + //! Returns: Nothing. //! //! Throws: If the predicate throws. Basic guarantee. //! @@ -1338,11 +1373,15 @@ class slist_impl //! size() + x.size() - 1 comparisons. //! //! Note: Iterators and references are not invalidated. + //! + //! Additional note: If optional "last" argument is passed, it is assigned + //! to an iterator to the last transferred value or end() is x is empty. template - iterator merge(slist_impl& x, Predicate p) + void merge(slist_impl& x, Predicate p, const_iterator *last = 0) { const_iterator e(this->cend()), ex(x.cend()), bb(this->cbefore_begin()), - bb_next, last_inserted(e); + bb_next; + if(last) *last = e.unconst(); while(!x.empty()){ const_iterator ibx_next(x.cbefore_begin()), ibx(ibx_next++); while (++(bb_next = bb) != e && !p(*ibx_next, *bb_next)){ @@ -1350,7 +1389,7 @@ class slist_impl } if(bb_next == e){ //Now transfer the rest to the end of the container - last_inserted = this->splice_after(bb, x); + this->splice_after(bb, x, last); break; } else{ @@ -1359,10 +1398,9 @@ class slist_impl ibx = ibx_next; ++n; } while(++(ibx_next = ibx) != ex && p(*ibx_next, *bb_next)); this->splice_after(bb, x, x.before_begin(), ibx, n); - last_inserted = ibx; + if(last) *last = ibx; } } - return last_inserted.unconst(); } //! Effects: This function removes all of x's elements and inserts them @@ -1618,14 +1656,7 @@ class slist_impl //! Complexity: Linear to the number of elements before i. //! Constant if cache_last<> is true and i == end(). iterator previous(iterator i) - { - if(cache_last && (i.pointed_node() == this->get_end_node())){ - return iterator(this->get_last_node(), this); - } - return iterator - (node_algorithms::get_previous_node - (this->before_begin().pointed_node(), i.pointed_node()), this); - } + { return this->previous(this->cbefore_begin(), i); } //! Returns: The const_iterator to the element before i in the list. //! Returns the end-const_iterator, if either i is the begin-const_iterator or @@ -1636,13 +1667,86 @@ class slist_impl //! Complexity: Linear to the number of elements before i. //! Constant if cache_last<> is true and i == end(). const_iterator previous(const_iterator i) const + { return this->previous(this->cbefore_begin(), i); } + + //! Returns: The iterator to the element before i in the list, + //! starting the search on element after prev_from. + //! Returns the end-iterator, if either i is the begin-iterator or the + //! list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + iterator previous(const_iterator prev_from, iterator i) + { return this->previous(prev_from, const_iterator(i)).unconst(); } + + //! Returns: The const_iterator to the element before i in the list, + //! starting the search on element after prev_from. + //! Returns the end-const_iterator, if either i is the begin-const_iterator or + //! the list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + const_iterator previous(const_iterator prev_from, const_iterator i) const { if(cache_last && (i.pointed_node() == this->get_end_node())){ return const_iterator(uncast(this->get_last_node()), this); } return const_iterator (node_algorithms::get_previous_node - (this->before_begin().pointed_node(), i.pointed_node()), this); + (prev_from.pointed_node(), i.pointed_node()), this); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end(). + //! + //! Effects: Transfers the range (before_first, before_last] to this + //! list, after the element pointed by prev_pos. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements transferred + //! if constant_time_size is true. Constant-time otherwise. + //! + //! Note: 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 incorporate_after(const_iterator prev_from, node_ptr first, node_ptr before_last) + { + if(constant_time_size) + this->incorporate_after(prev_from, first, before_last, std::distance(first, before_last)+1); + else + this->priv_incorporate_after + (prev_from.pointed_node(), first, before_last); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end() and + //! n == std::distance(first, before_last) + 1. + //! + //! Effects: Transfers the range (before_first, before_last] from list x to this + //! list, after the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: 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 incorporate_after(const_iterator prev_pos, node_ptr first, node_ptr before_last, difference_type n) + { + if(n){ + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(iterator(first, this), iterator(before_last, this))+1 == n); + this->priv_incorporate_after(prev_pos.pointed_node(), first, before_last); + if(constant_time_size){ + this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); + } + } } private: @@ -1662,6 +1766,16 @@ class slist_impl } } + void priv_incorporate_after(node_ptr prev_pos_n, node_ptr first_n, node_ptr before_last_n) + { + if(cache_last){ + if(node_traits::get_next(prev_pos_n) == this->get_end_node()){ + this->set_last_node(before_last_n); + } + } + node_algorithms::incorporate_after(prev_pos_n, first_n, before_last_n); + } + void priv_reverse(detail::bool_) { node_algorithms::reverse(this->get_root_node()); } diff --git a/include/boost/intrusive/slist_hook.hpp b/include/boost/intrusive/slist_hook.hpp index 7779b98..1debe66 100644 --- a/include/boost/intrusive/slist_hook.hpp +++ b/include/boost/intrusive/slist_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -96,6 +96,7 @@ class slist_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -218,6 +219,7 @@ class slist_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 79bdbc1..9727d14 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -624,7 +624,7 @@ class splay_set_impl /// @cond , typename detail::enable_if_c::value >::type * = 0 /// @endcond -) + ) { return tree_.erase_and_dispose(key, comp, disposer); } //! Effects: Erases all the elements of the container. diff --git a/include/boost/intrusive/splay_set_hook.hpp b/include/boost/intrusive/splay_set_hook.hpp index 472fde3..d42f4c8 100644 --- a/include/boost/intrusive/splay_set_hook.hpp +++ b/include/boost/intrusive/splay_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -93,6 +93,7 @@ class splay_set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -216,6 +217,7 @@ class splay_set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index 971f846..4020c85 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -115,7 +115,7 @@ class splaytree_impl typedef splaytree_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::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -895,7 +895,6 @@ class splaytree_impl { node_algorithms::clear_and_dispose(node_ptr(&priv_header()) , detail::node_disposer(disposer, this)); - node_algorithms::init_header(&priv_header()); this->priv_size_traits().set_size(0); } diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index e727ab6..eb25e9f 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -543,6 +543,79 @@ class splaytree_algorithms return tree_algorithms::insert_equal(header, hint, new_node, comp); } + + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid iterator or header (end) node. + //! "pos" must be an iterator pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node) + { + tree_algorithms::insert_before(header, pos, new_node); + splay_up(new_node, header); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_back(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_back(header, new_node); + splay_up(new_node, header); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! + //! Effects: Inserts new_node into the tree before "pos". + //! + //! Complexity: Constant-time. + //! + //! Throws: Nothing. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + static void push_front(node_ptr header, node_ptr new_node) + { + tree_algorithms::push_front(header, new_node); + splay_up(new_node, header); + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_upper_bound (node_ptr header, node_ptr new_node, NodePtrCompare comp) @@ -551,6 +624,18 @@ class splaytree_algorithms return tree_algorithms::insert_equal_upper_bound(header, new_node, comp); } + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. template static node_ptr insert_equal_lower_bound (node_ptr header, node_ptr new_node, NodePtrCompare comp) @@ -605,9 +690,8 @@ class splaytree_algorithms // if( data_->parent == t ) // data_->parent = find_leftmost(); //posibility 1 - if(splay && NodeTraits::get_left(z) != 0 ){ - node_ptr l = prev_node(z); - splay_up(l, header); + if(splay && NodeTraits::get_left(z)){ + splay_up(prev_node(z), header); } /* //possibility 2 @@ -644,8 +728,8 @@ class splaytree_algorithms if( n == t ) return; for( ;; ){ - node_ptr p = NodeTraits::get_parent(n); - node_ptr g = NodeTraits::get_parent(p); + node_ptr p(NodeTraits::get_parent(n)); + node_ptr g(NodeTraits::get_parent(p)); if( p == t ) break; @@ -688,9 +772,8 @@ class splaytree_algorithms if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) return t; //Backup leftmost/rightmost - node_ptr leftmost = NodeTraits::get_left(header); - node_ptr rightmost = NodeTraits::get_right(header); - + node_ptr leftmost (NodeTraits::get_left(header)); + node_ptr rightmost(NodeTraits::get_right(header)); { detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); node_ptr null = header; diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index 7298db3..b7c9ed2 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -119,7 +119,7 @@ class treap_impl typedef treap_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::value; + static const bool stateful_value_traits = detail::is_stateful_value_traits::value; /// @cond private: @@ -217,7 +217,7 @@ class treap_impl typedef typename node_algorithms::insert_commit_data insert_commit_data; - //! Effects: Constructs an empty tree. + //! Effects: Constructs an empty treap. //! //! Complexity: Constant. //! @@ -236,7 +236,7 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue of type value_type. //! cmp must be a comparison function that induces a strict weak ordering. //! - //! Effects: Constructs an empty tree and inserts elements from + //! Effects: Constructs an empty treap and inserts elements from //! [b, e). //! //! Complexity: Linear in N if [b, e) is already sorted using @@ -272,7 +272,7 @@ class treap_impl ~treap_impl() {} - //! Effects: Returns an iterator pointing to the beginning of the tree. + //! Effects: Returns an iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -280,7 +280,7 @@ class treap_impl iterator begin() { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! Effects: Returns a const_iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -288,7 +288,7 @@ class treap_impl const_iterator begin() const { return this->cbegin(); } - //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! Effects: Returns a const_iterator pointing to the beginning of the treap. //! //! Complexity: Constant. //! @@ -296,7 +296,7 @@ class treap_impl const_iterator cbegin() const { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); } - //! Effects: Returns an iterator pointing to the end of the tree. + //! Effects: Returns an iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -304,7 +304,7 @@ class treap_impl iterator end() { return iterator (node_ptr(&priv_header()), this); } - //! Effects: Returns a const_iterator pointing to the end of the tree. + //! Effects: Returns a const_iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -312,7 +312,7 @@ class treap_impl const_iterator end() const { return this->cend(); } - //! Effects: Returns a const_iterator pointing to the end of the tree. + //! Effects: Returns a const_iterator pointing to the end of the treap. //! //! Complexity: Constant. //! @@ -321,7 +321,7 @@ class treap_impl { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } - //! Effects: Returns an iterator pointing to the highest priority object of the tree. + //! Effects: Returns an iterator pointing to the highest priority object of the treap. //! //! Complexity: Constant. //! @@ -329,7 +329,7 @@ class treap_impl iterator top() { return this->empty() ? this->end() : iterator (node_traits::get_parent(node_ptr(&priv_header())), this); } - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. + //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! //! Complexity: Constant. //! @@ -337,7 +337,7 @@ class treap_impl const_iterator top() const { return this->ctop(); } - //! Effects: Returns a const_iterator pointing to the highest priority object of the tree.. + //! Effects: Returns a const_iterator pointing to the highest priority object of the treap.. //! //! Complexity: Constant. //! @@ -346,7 +346,7 @@ class treap_impl { return this->empty() ? this->cend() : const_iterator (node_traits::get_parent(const_node_ptr(&priv_header())), this); } //! Effects: Returns a reverse_iterator pointing to the beginning of the - //! reversed tree. + //! reversed treap. //! //! Complexity: Constant. //! @@ -355,7 +355,7 @@ class treap_impl { return reverse_iterator(this->end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -364,7 +364,7 @@ class treap_impl { return const_reverse_iterator(this->end()); } //! Effects: Returns a const_reverse_iterator pointing to the beginning - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -373,7 +373,7 @@ class treap_impl { return const_reverse_iterator(this->end()); } //! Effects: Returns a reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -382,7 +382,7 @@ class treap_impl { return reverse_iterator(this->begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -391,7 +391,7 @@ class treap_impl { return const_reverse_iterator(this->begin()); } //! Effects: Returns a const_reverse_iterator pointing to the end - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -400,7 +400,7 @@ class treap_impl { return const_reverse_iterator(this->begin()); } //! Effects: Returns a reverse_iterator pointing to the highest priority object of the - //! reversed tree. + //! reversed treap. //! //! Complexity: Constant. //! @@ -409,7 +409,7 @@ class treap_impl { return reverse_iterator(this->top()); } //! Effects: Returns a const_reverse_iterator pointing to the highest priority objec - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -418,7 +418,7 @@ class treap_impl { return const_reverse_iterator(this->top()); } //! Effects: Returns a const_reverse_iterator pointing to the highest priority object - //! of the reversed tree. + //! of the reversed treap. //! //! Complexity: Constant. //! @@ -451,7 +451,7 @@ class treap_impl //! Precondition: it must be a valid iterator //! of treap. //! - //! Effects: Returns a const reference to the tree associated to the iterator + //! Effects: Returns a const reference to the treap associated to the iterator //! //! Throws: Nothing. //! @@ -462,7 +462,7 @@ class treap_impl //! Precondition: it must be a valid end const_iterator //! of treap. //! - //! Effects: Returns a const reference to the tree associated to the end iterator + //! Effects: Returns a const reference to the treap associated to the end iterator //! //! Throws: Nothing. //! @@ -470,7 +470,7 @@ class treap_impl static const treap_impl &container_from_iterator(const_iterator it) { return priv_container_from_iterator(it); } - //! Effects: Returns the value_compare object used by the tree. + //! Effects: Returns the value_compare object used by the treap. //! //! Complexity: Constant. //! @@ -478,7 +478,7 @@ class treap_impl value_compare value_comp() const { return this->priv_comp(); } - //! Effects: Returns the priority_compare object used by the tree. + //! Effects: Returns the priority_compare object used by the treap. //! //! Complexity: Constant. //! @@ -494,7 +494,7 @@ class treap_impl bool empty() const { return node_algorithms::unique(const_node_ptr(&priv_header())); } - //! Effects: Returns the number of elements stored in the tree. + //! Effects: Returns the number of elements stored in the treap. //! //! Complexity: Linear to elements contained in *this //! if constant-time size option is disabled. Constant time otherwise. @@ -531,12 +531,12 @@ class treap_impl //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the tree before the upper bound. + //! Effects: Inserts value into the treap before the upper bound. //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -557,14 +557,14 @@ class treap_impl //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator. //! - //! Effects: Inserts x into the tree, using "hint" as a hint to + //! Effects: Inserts x into the treap, using "hint" as a hint to //! where it will be inserted. If "hint" is the upper_bound //! the insertion takes constant time (two comparisons in the worst case) //! //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -585,14 +585,14 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Inserts a each element of a range into the tree + //! Effects: Inserts a each element of a range into the treap //! before the upper bound of the key of each element. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -607,13 +607,13 @@ class treap_impl //! Requires: value must be an lvalue //! - //! Effects: Inserts value into the tree if the value + //! Effects: Inserts value into the treap if the value //! is not already present. //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -630,14 +630,14 @@ class treap_impl //! Requires: value must be an lvalue, and "hint" must be //! a valid iterator //! - //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! Effects: Tries to insert x into the treap, using "hint" as a hint //! to where it will be inserted. //! //! Complexity: Logarithmic in general, but it is amortized //! constant time (two comparisons in the worst case) //! if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -654,13 +654,13 @@ class treap_impl //! Requires: Dereferencing iterator must yield an lvalue //! of type value_type. //! - //! Effects: Tries to insert each element of a range into the tree. + //! Effects: Tries to insert each element of a range into the treap. //! //! Complexity: Insert range is in general O(N * log(N)), where N is the //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare or priority_compare funcstions throw. + //! Throws: If the internal value_compare or priority_compare functions throw. //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. @@ -680,8 +680,10 @@ class treap_impl } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself. @@ -694,7 +696,8 @@ class treap_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the key_value_comp or key_value_pcomp + //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -725,8 +728,10 @@ class treap_impl } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an arbitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the container, using //! a user provided key instead of the value itself, using "hint" @@ -741,7 +746,8 @@ class treap_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If the key_value_comp or key_value_pcomp + //! ordering functions throw. Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -800,6 +806,82 @@ class treap_impl return iterator(to_insert, this); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + return iterator(node_algorithms::insert_before + (node_ptr(&priv_header()), pos.pointed_node(), to_insert, pcomp), this); + } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + node_algorithms::push_back(node_ptr(&priv_header()), to_insert, pcomp); + } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + detail::key_nodeptr_comp + pcomp(priv_pcomp(), this); + node_algorithms::push_front(node_ptr(&priv_header()), to_insert, pcomp); + } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity for erase element is constant time. @@ -817,7 +899,7 @@ class treap_impl BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); detail::key_nodeptr_comp key_node_pcomp(priv_pcomp(), this); - node_algorithms::erase(&priv_header(), to_erase,key_node_pcomp); + node_algorithms::erase(&priv_header(), to_erase, key_node_pcomp); this->priv_size_traits().decrement(); if(safemode_or_autounlink) node_algorithms::init(to_erase); @@ -856,7 +938,8 @@ class treap_impl //! //! Complexity: O(log(size() + N). //! - //! Throws: if the internal priority_compare function throws. Strong guarantee. + //! Throws: if the internal priority_compare function throws. + //! Equivalent guarantee to while(beg != end) erase(beg++); //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1260,16 +1343,16 @@ class treap_impl } } - //! Effects: Unlinks the leftmost node from the tree. + //! Effects: Unlinks the leftmost node from the treap. //! //! Complexity: Average complexity is constant time. //! //! Throws: Nothing. //! - //! Notes: This function breaks the tree and the tree can + //! Notes: This function breaks the treap and the treap can //! only be used for more unlink_leftmost_without_rebalance calls. //! This function is normally used to achieve a step by step - //! controlled destruction of the tree. + //! controlled destruction of the treap. pointer unlink_leftmost_without_rebalance() { node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance @@ -1283,10 +1366,10 @@ class treap_impl } //! Requires: replace_this must be a valid iterator of *this - //! and with_this must not be inserted in any tree. + //! and with_this must not be inserted in any treap. //! //! Effects: Replaces replace_this in its position in the - //! tree with with_this. The tree does not need to be rebalanced. + //! treap with with_this. The treap does not need to be rebalanced. //! //! Complexity: Constant. //! @@ -1363,7 +1446,7 @@ class treap_impl const_iterator iterator_to(const_reference value) const { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } - //! Requires: value shall not be in a tree. + //! Requires: value shall not be in a treap. //! //! Effects: init_node puts the hook of a value in a well-known default //! state. diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index bdceac2..6c05efa 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -10,8 +10,8 @@ // ///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP -#define BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP +#ifndef BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP #include @@ -270,15 +270,15 @@ class treap_algorithms //! //! Complexity: Average complexity is constant time. //! - //! Throws: Nothing. - template - static void unlink(node_ptr node, NodePriorityCompare prio) + //! Throws: If "pcomp" throws, strong guarantee + template + static void unlink(node_ptr node, NodePtrPriorityCompare pcomp) { node_ptr x = NodeTraits::get_parent(node); if(x){ while(!is_header(x)) x = NodeTraits::get_parent(x); - erase(x, node, prio); + erase(x, node, pcomp); } } @@ -383,9 +383,9 @@ class treap_algorithms //! //! Complexity: Amortized constant time. //! - //! Throws: Nothing. - template - static node_ptr erase(node_ptr header, node_ptr z, NodePriorityCompare pcomp) + //! Throws: If "pcomp" throws, strong guarantee. + template + static node_ptr erase(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp) { rebalance_for_erasure(header, z, pcomp); tree_algorithms::erase(header, z); @@ -503,23 +503,24 @@ class treap_algorithms //! NodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! //! Effects: Inserts new_node into the tree before the upper bound - //! according to "comp". + //! according to "comp" and rotates the tree according to "pcomp". //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If "comp" throws. - template + //! Throws: If "comp" throw or "pcomp" throw. + template static node_ptr insert_equal_upper_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, PriorityNodeCompare pcomp) + (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_upper_bound_check(h, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -527,23 +528,24 @@ class treap_algorithms //! NodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! - //! Effects: Inserts new_node into the tree before the lower bound - //! according to "comp". + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp" and rotates the tree according to "pcomp". //! //! Complexity: Average complexity for insert element is at //! most logarithmic. //! //! Throws: If "comp" throws. - template + template static node_ptr insert_equal_lower_bound - (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePriorityCompare pcomp) + (node_ptr h, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_lower_bound_check(h, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } @@ -552,27 +554,107 @@ class treap_algorithms //! ordering compatible with the strict weak ordering used to create the //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from //! the "header"'s tree. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. //! //! Effects: Inserts new_node into the tree, using "hint" as a hint to //! where it will be inserted. If "hint" is the upper_bound //! the insertion takes constant time (two comparisons in the worst case). + //! Rotates the tree according to "pcomp". //! //! Complexity: Logarithmic in general, but it is amortized //! constant time if new_node is inserted immediately before "hint". //! - //! Throws: If "comp" throws. - template + //! Throws: If "comp" throw or "pcomp" throw. + template static node_ptr insert_equal - (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePriorityCompare pcomp) + (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp, NodePtrPriorityCompare pcomp) { insert_commit_data commit_data; tree_algorithms::insert_equal_check(h, hint, new_node, comp, commit_data); - rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); - tree_algorithms::insert_unique_commit(h, new_node, commit_data); - rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + rebalance_check_and_commit(h, new_node, pcomp, commit_data); return new_node; } + //! Requires: "header" must be the header node of a tree. + //! "pos" must be a valid node of the tree (including header end) node. + //! "pos" must be a node pointing to the successor to "new_node" + //! once inserted according to the order of already inserted nodes. This function does not + //! check "pos" and this precondition must be guaranteed by the caller. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before "pos" + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "pos" is not the successor of the newly inserted "new_node" + //! tree invariants might be broken. + template + static node_ptr insert_before + (node_ptr header, node_ptr pos, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::insert_before_check(header, pos, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering no less than the + //! greatest inserted key. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts x into the tree in the last position + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "new_node" is less than the greatest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_back(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::push_back_check(header, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + } + + //! Requires: "header" must be the header node of a tree. + //! "new_node" must be, according to the used ordering, no greater than the + //! lowest inserted key. + //! NodePtrPriorityCompare is a priority function object that induces a strict weak + //! ordering compatible with the one used to create the + //! the tree. NodePtrPriorityCompare compares two node_ptrs. + //! + //! Effects: Inserts x into the tree in the first position + //! and rotates the tree according to "pcomp". + //! + //! Complexity: Constant-time. + //! + //! Throws: If "pcomp" throws, strong guarantee. + //! + //! Note: If "new_node" is greater than the lowest inserted key + //! tree invariants are broken. This function is slightly faster than + //! using "insert_before". + template + static void push_front(node_ptr header, node_ptr new_node, NodePtrPriorityCompare pcomp) + { + insert_commit_data commit_data; + tree_algorithms::push_front_check(header, commit_data); + rebalance_check_and_commit(header, new_node, pcomp, commit_data); + } + //! Requires: "header" must be the header node of a tree. //! KeyNodePtrCompare is a function object that induces a strict weak //! ordering compatible with the strict weak ordering used to create the @@ -720,8 +802,8 @@ class treap_algorithms return tree_algorithms::is_header(p); } - template - static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePriorityCompare pcomp) + template + static void rebalance_for_erasure(node_ptr header, node_ptr z, NodePtrPriorityCompare pcomp) { std::size_t n = 0; rerotate_on_destroy rb(header, z, n); @@ -742,6 +824,17 @@ class treap_algorithms rb.release(); } + template + static void rebalance_check_and_commit + (node_ptr h, node_ptr new_node, NodePtrPriorityCompare pcomp, insert_commit_data &commit_data) + { + rebalance_after_insertion_check(h, commit_data.node, new_node, pcomp, commit_data.rotations); + //No-throw + tree_algorithms::insert_unique_commit(h, new_node, commit_data); + rebalance_after_insertion_commit(h, new_node, commit_data.rotations); + } + + template static void rebalance_after_insertion_check ( const_node_ptr header, const_node_ptr upnode, const Key &k @@ -759,7 +852,7 @@ class treap_algorithms static void rebalance_after_insertion_commit(node_ptr header, node_ptr p, std::size_t n) { - // Now to n rotations + // Now execute n rotations for( node_ptr p_parent = NodeTraits::get_parent(p) ; n-- ; p_parent = NodeTraits::get_parent(p)){ @@ -773,8 +866,8 @@ class treap_algorithms } } - template - static bool check_invariant(const_node_ptr header, NodePriorityCompare pcomp) + template + static bool check_invariant(const_node_ptr header, NodePtrPriorityCompare pcomp) { node_ptr beg = begin_node(header); node_ptr end = end_node(header); @@ -798,4 +891,4 @@ class treap_algorithms #include -#endif //BOOST_INTRUSIVE_TRIE_ALGORITHMS_HPP +#endif //BOOST_INTRUSIVE_TREAP_ALGORITHMS_HPP diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 9322a6b..12611ee 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -351,6 +351,14 @@ class treap_set_impl value_compare value_comp() const { return tree_.value_comp(); } + //! Effects: Returns the priority_compare object used by the treap_set. + //! + //! Complexity: Constant. + //! + //! Throws: If priority_compare copy-constructor throws. + priority_compare priority_comp() const + { return tree_.priority_comp(); } + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. @@ -408,7 +416,8 @@ class treap_set_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering function throw. + //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -426,7 +435,8 @@ class treap_set_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! functions throw. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -434,8 +444,10 @@ class treap_set_impl { return tree_.insert_unique(hint, value); } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the treap_set, using //! a user provided key instead of the value itself. @@ -448,7 +460,8 @@ class treap_set_impl //! //! Complexity: Average complexity is at most logarithmic. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If key_value_comp or key_value_pcomp ordering function throw. + //! Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -463,14 +476,17 @@ class treap_set_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the treap_set. - template + template std::pair insert_check - (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + ( const KeyType &key, KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + , insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, key_value_pcomp, commit_data); } //! Requires: key_value_comp must be a comparison function that induces - //! the same strict weak ordering as value_compare. The difference is that - //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! the same strict weak ordering as value_compare. + //! key_value_pcomp must be a comparison function that induces + //! the same strict weak ordering as priority_compare. The difference is that + //! key_value_pcomp and key_value_comp compare an arbitrary key with the contained values. //! //! Effects: Checks if a value can be inserted in the treap_set, using //! a user provided key instead of the value itself, using "hint" @@ -485,7 +501,8 @@ class treap_set_impl //! Complexity: Logarithmic in general, but it's amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! Throws: If key_value_comp or key_value_pcomp ordering function throw. + //! Strong guarantee. //! //! Notes: This function is used to improve performance when constructing //! a value_type is expensive: if there is an equivalent value @@ -500,11 +517,12 @@ class treap_set_impl //! //! "commit_data" remains valid for a subsequent "insert_commit" only if no more //! objects are inserted or erased from the treap_set. - template + template std::pair insert_check - (const_iterator hint, const KeyType &key - ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) - { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + ( const_iterator hint, const KeyType &key + , KeyValueCompare key_value_comp, KeyValuePriorityCompare key_value_pcomp + , insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, key_value_pcomp, commit_data); } //! Requires: value must be an lvalue of type value_type. commit_data //! must have been obtained from a previous call to "insert_check". @@ -535,7 +553,8 @@ class treap_set_impl //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If the internal value_compare or priority_compare ordering function + //! throw. Basic guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -543,13 +562,65 @@ class treap_set_impl void insert(Iterator b, Iterator e) { tree_.insert_unique(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate. "value" must not be equal to any + //! inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be greater than + //! any inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be less + //! than any inserted key according to the predicate. + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -563,7 +634,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased elements. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -576,7 +647,8 @@ class treap_set_impl //! //! Complexity: O(log(size()) + this->count(value)). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If internal value_compare or priority_compare + //! ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -590,7 +662,8 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If the comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare + //! ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -611,7 +684,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -635,7 +708,7 @@ class treap_set_impl //! //! Returns: An iterator to the element after the erased elements. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -652,7 +725,7 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(value)). Basic guarantee. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -670,7 +743,8 @@ class treap_set_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. + //! Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1584,6 +1658,14 @@ class treap_multiset_impl value_compare value_comp() const { return tree_.value_comp(); } + //! Effects: Returns the priority_compare object used by the treap_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If priority_compare copy-constructor throws. + priority_compare priority_comp() const + { return tree_.priority_comp(); } + //! Effects: Returns true if the container is empty. //! //! Complexity: Constant. @@ -1638,7 +1720,8 @@ class treap_multiset_impl //! Complexity: Average complexity for insert element is at //! most logarithmic. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! function throws. Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1656,7 +1739,8 @@ class treap_multiset_impl //! Complexity: Logarithmic in general, but it is amortized //! constant time if t is inserted immediately before hint. //! - //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! Throws: If internal value_compare or priority_compare ordering functions throw. + //! Strong guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1675,7 +1759,8 @@ class treap_multiset_impl //! size of the range. However, it is linear in N if the range is already sorted //! by value_comp(). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If internal value_compare or priority_compare ordering functions throw. + //! Basic guarantee. //! //! Note: Does not affect the validity of iterators and references. //! No copy-constructors are called. @@ -1683,13 +1768,64 @@ class treap_multiset_impl void insert(Iterator b, Iterator e) { tree_.insert_equal(b, e); } + //! Requires: value must be an lvalue, "pos" must be + //! a valid iterator (or end) and must be the succesor of value + //! once inserted according to the predicate + //! + //! Effects: Inserts x into the treap before "pos". + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if "pos" is not + //! the successor of "value" treap ordering invariant will be broken. + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + iterator insert_before(const_iterator pos, reference value) + { return tree_.insert_before(pos, value); } + + //! Requires: value must be an lvalue, and it must be no less + //! than the greatest inserted key. + //! + //! Effects: Inserts x into the treap in the last position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! less than the greatest inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_back(reference value) + { tree_.push_back(value); } + + //! Requires: value must be an lvalue, and it must be no greater + //! than the minimum inserted key + //! + //! Effects: Inserts x into the treap in the first position. + //! + //! Complexity: Constant time. + //! + //! Throws: If the internal priority_compare function throws. Strong guarantee. + //! + //! Note: This function does not check preconditions so if value is + //! greater than the minimum inserted key treap ordering invariant will be broken. + //! This function is slightly more efficient than using "insert_before". + //! This is a low-level function to be used only for performance reasons + //! by advanced users. + void push_front(reference value) + { tree_.push_front(value); } + //! Effects: Erases the element pointed to by pos. //! //! Complexity: Average complexity is constant time. //! //! Returns: An iterator to the element after the erased element. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1703,7 +1839,7 @@ class treap_multiset_impl //! Complexity: Average complexity for erase range is at most //! O(log(size() + N)), where N is the number of elements in the range. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1716,7 +1852,8 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(value)). //! - //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! Throws: If the internal value_compare or priority_compare ordering + //! functiona throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1730,7 +1867,7 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. @@ -1751,7 +1888,7 @@ class treap_multiset_impl //! //! Complexity: Average complexity for erase element is constant time. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Strong guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1775,7 +1912,7 @@ class treap_multiset_impl //! Complexity: Average complexity for erase range is at most //! O(log(size() + N)), where N is the number of elements in the range. //! - //! Throws: Nothing. + //! Throws: If the internal priority_compare function throws. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. @@ -1810,7 +1947,7 @@ class treap_multiset_impl //! //! Complexity: O(log(size() + this->count(key, comp)). //! - //! Throws: If comp ordering function throws. Basic guarantee. + //! Throws: If comp or internal priority_compare ordering functions throw. Basic guarantee. //! //! Note: Invalidates the iterators //! to the erased elements. diff --git a/include/boost/intrusive/trivial_value_traits.hpp b/include/boost/intrusive/trivial_value_traits.hpp index dcf996d..4527d7c 100644 --- a/include/boost/intrusive/trivial_value_traits.hpp +++ b/include/boost/intrusive/trivial_value_traits.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index cdca860..47d1aab 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -395,8 +395,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_.erase(i); } + iterator erase(const_iterator i) + { return table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -407,8 +407,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + iterator erase(const_iterator b, const_iterator e) + { return table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -460,15 +460,13 @@ class unordered_set_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) { return table_.erase_and_dispose(i, disposer); } - #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) - template - iterator erase_and_dispose(iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } - #endif - //! Requires: Disposer::operator()(pointer) shouldn't throw. //! //! Effects: Erases the range pointed to by b end e. @@ -1370,9 +1368,8 @@ class unordered_multiset_impl //! //! Effects: Equivalent to this->insert(t) for each element in [b, e). //! - //! Complexity: Insert range is in general O(N * log(N)), where N is the - //! size of the range. However, it is linear in N if the range is already sorted - //! by value_comp(). + //! Complexity: Average case is O(N), where N is the + //! size of the range. //! //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. //! @@ -1390,8 +1387,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - void erase(const_iterator i) - { table_.erase(i); } + iterator erase(const_iterator i) + { return table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -1402,8 +1399,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - void erase(const_iterator b, const_iterator e) - { table_.erase(b, e); } + iterator erase(const_iterator b, const_iterator e) + { return table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -1456,12 +1453,16 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator i, Disposer disposer) - { table_.erase_and_dispose(i, disposer); } + iterator erase_and_dispose(const_iterator i, Disposer disposer + /// @cond + , typename detail::enable_if_c::value >::type * = 0 + /// @endcond + ) + { return table_.erase_and_dispose(i, disposer); } #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template - iterator erase_and_dispose(iterator i, Disposer disposer) + iterator erase_and_dispose(const_iterator i, Disposer disposer) { return this->erase_and_dispose(const_iterator(i), disposer); } #endif @@ -1478,8 +1479,8 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { table_.erase_and_dispose(b, e, disposer); } + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { return table_.erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index adb3a8d..286b318 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -222,6 +222,7 @@ class unordered_set_base_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! @@ -351,6 +352,7 @@ class unordered_set_member_hook >::type { #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) + public: //! Effects: If link_mode is \c auto_unlink or \c safe_link //! initializes the node to an unlinked state. //! From 36f09b769884d62f459f19648e4b67e6b3a0bdcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 14 Oct 2009 13:08:04 +0000 Subject: [PATCH 14/29] Fixes for 1.41 [SVN r56823] --- CMakeLists.txt | 6 - doc/intrusive.qbk | 50 ++++++-- example/doc_advanced_value_traits.cpp | 2 +- example/doc_advanced_value_traits2.cpp | 2 +- example/doc_assoc_optimized_code.cpp | 2 +- example/doc_auto_unlink.cpp | 2 +- example/doc_avl_set.cpp | 2 +- example/doc_avltree_algorithms.cpp | 2 +- example/doc_bucket_traits.cpp | 2 +- example/doc_clone_from.cpp | 2 +- example/doc_entity.cpp | 2 +- example/doc_erasing_and_disposing.cpp | 2 +- example/doc_external_value_traits.cpp | 2 +- example/doc_how_to_use.cpp | 2 +- example/doc_iterator_from_value.cpp | 2 +- example/doc_list.cpp | 2 +- example/doc_list_algorithms.cpp | 2 +- example/doc_offset_ptr.cpp | 2 +- example/doc_positional_insertion.cpp | 74 ++++++++++++ example/doc_rbtree_algorithms.cpp | 2 +- example/doc_set.cpp | 2 +- example/doc_sg_set.cpp | 2 +- example/doc_slist.cpp | 2 +- example/doc_slist_algorithms.cpp | 2 +- example/doc_splay_algorithms.cpp | 2 +- example/doc_splay_set.cpp | 2 +- example/doc_splaytree_algorithms.cpp | 2 +- example/doc_stateful_value_traits.cpp | 2 +- example/doc_treap_algorithms.cpp | 2 +- example/doc_treap_set.cpp | 2 +- example/doc_unordered_set.cpp | 2 +- example/doc_value_traits.cpp | 2 +- example/doc_window.cpp | 2 +- index.html | 2 +- perf/perf_list.cpp | 2 +- .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 9 ++ proj/vc7ide/to-do.txt | 16 +-- test/any_test.cpp | 2 +- test/avl_multiset_test.cpp | 22 +++- test/avl_set_test.cpp | 23 +++- test/common_functors.hpp | 2 +- test/custom_bucket_traits_test.cpp | 2 +- test/default_hook_test.cpp | 2 +- test/external_value_traits_test.cpp | 2 +- test/generic_assoc_test.hpp | 79 +++++++++++- test/generic_multiset_test.hpp | 2 +- test/generic_set_test.hpp | 112 ++++++++++++++---- test/itestvalue.hpp | 34 +++++- test/list_test.cpp | 2 +- test/make_functions_test.cpp | 2 +- test/multiset_test.cpp | 22 +++- test/set_test.cpp | 24 +++- test/sg_multiset_test.cpp | 19 ++- test/sg_set_test.cpp | 16 +++ test/slist_test.cpp | 2 +- test/splay_multiset_test.cpp | 2 +- test/stateful_value_traits_test.cpp | 2 +- test/test_container.hpp | 106 ++++++++++++++++- test/test_macros.hpp | 2 +- test/treap_multiset_test.cpp | 22 +++- test/treap_set_test.cpp | 39 +++++- test/unordered_multiset_test.cpp | 22 +++- test/unordered_set_test.cpp | 22 +++- test/virtual_base_test.cpp | 2 +- 64 files changed, 690 insertions(+), 117 deletions(-) create mode 100644 example/doc_positional_insertion.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3169cb1..73434d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,3 @@ -# -# Copyright Troy D. Straszheim -# -# Distributed under the Boost Software License, Version 1.0. -# See http://www.boost.org/LICENSE_1_0.txt -# #---------------------------------------------------------------------------- # This file was automatically generated from the original CMakeLists.txt file # Add a variable to hold the headers for the library diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index df7dded..c37883a 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1,14 +1,14 @@ [/ - / Copyright (c) 2007 Ion Gaztanaga + / Copyright (c) 2007-2009 Ion Gaztanaga / / 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) /] [library Boost.Intrusive - [quickbook 1.3] + [quickbook 1.4] [authors [Krzikalla, Olaf], [Gaztanaga, Ion]] - [copyright 2005 Olaf Krzikalla, 2006-2008 Ion Gaztanaga] + [copyright 2005 Olaf Krzikalla, 2006-2009 Ion Gaztanaga] [id intrusive] [dirname intrusive] [purpose Intrusive containers] @@ -2069,13 +2069,38 @@ With multiple ordered and unordered associative containers [classref boost::intrusive::unordered_multiset unordered_multiset]) there is no need for these advanced insertion functions, since insertions are always successful. +[endsect] + +[section:positional_insertions Positional insertions] + +Some ordered associative containers offer low-level functions to bypass ordering +checks and insert nodes directly in desired tree positions. These functions are +provided for performance reasons when values to be inserted in the container are +known to fulfill order (sets and multisets) and uniqueness (sets) invariants. A +typical usage of these functions is when intrusive associative containers are used +to build non-intrusive containers and the programmer wants to speed up assignments +from other associative containers: if the ordering and uniqueness properties are the same, +there is no need to waste time checking the position of each source value, because values +are already ordered: back insertions will be much more efficient. + +[*Note:] These functions [*don't check preconditions] so they must used with care. These +are functions are low-level operations [*will break container invariants if +ordering and uniqueness preconditions are not assured by the caller.] + +Let's see an example: + +[import ../example/doc_positional_insertion.cpp] +[doc_positional_insertion] + + [endsect] For more information about advanced lookup and insertion functions see +associative containers' documentation (e.g. [classref boost::intrusive::set set], [classref boost::intrusive::multiset multiset], [classref boost::intrusive::unordered_set unordered_set] and -[classref boost::intrusive::unordered_multiset unordered_multiset] references. +[classref boost::intrusive::unordered_multiset unordered_multiset] references). [endsect] @@ -2269,7 +2294,7 @@ decide to insert two hooks in the same class. However, there is a more size-efficient alternative in [*Boost.Intrusive]: "any" hooks ([classref boost::intrusive::any_base_hook any_base_hook] and -[classref boost::intrusive::any_member_hook any_member_hook]. +[classref boost::intrusive::any_member_hook any_member_hook]). These hooks can be used to store a type in several containers offered by [*Boost.Intrusive] minimizing the size of the class. @@ -2288,8 +2313,8 @@ These hooks support these options: internally in the hook and propagated to the container. Default: `void_pointer`. -`auto_unlink` can't be supported because the hook does not know in which type of might -be inserted container. Additionally, these hooks don't support `unlink()` and +`auto_unlink` can't be supported because the hook does not know in which type of +container might be currently inserted. Additionally, these hooks don't support `unlink()` and `swap_nodes()` operations for the same reason. Here is an example that creates a class with two any hooks, and uses one to insert the @@ -3157,13 +3182,12 @@ to define the needed value traits classes: Until now all shown custom value traits are stateless, that is, [*the transformation between nodes and values is implemented in terms of static functions]. It's possible to use [*stateful] value traits so that we can separate nodes and values and [*avoid modifying types to insert nodes]. -[*Boost.Intrusive] differentiates between stateful and stateless value traits by checking if the ValueTraits -class is empty: +[*Boost.Intrusive] differentiates between stateful and stateless value traits by checking if all +Node <-> Value transformation functions are static or not: -* If the class is empty, a [*stateless] value traits is assumed. - Node <-> Value transformations must be static functions. -* If the class is not empty, a [*stateful] value traits is assumed. - Node <-> Value transformations must be non-static functions. +* If all Node <-> Value transformation functions are static , a [*stateless] + value traits is assumed. transformations must be static functions. +* Otherwise a [*stateful] value traits is assumed. Using stateful value traits it's possible to create containers of non-copyable/movable objects [*without modifying] the definition of the class to be inserted. This interesting property is achieved without using global variables diff --git a/example/doc_advanced_value_traits.cpp b/example/doc_advanced_value_traits.cpp index dca6585..835f234 100644 --- a/example/doc_advanced_value_traits.cpp +++ b/example/doc_advanced_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_advanced_value_traits2.cpp b/example/doc_advanced_value_traits2.cpp index ec9214e..48193b6 100644 --- a/example/doc_advanced_value_traits2.cpp +++ b/example/doc_advanced_value_traits2.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_assoc_optimized_code.cpp b/example/doc_assoc_optimized_code.cpp index 7b86a70..915f2c2 100644 --- a/example/doc_assoc_optimized_code.cpp +++ b/example/doc_assoc_optimized_code.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_auto_unlink.cpp b/example/doc_auto_unlink.cpp index 208fc6f..28a84ac 100644 --- a/example/doc_auto_unlink.cpp +++ b/example/doc_auto_unlink.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_avl_set.cpp b/example/doc_avl_set.cpp index 985c136..96ef64a 100644 --- a/example/doc_avl_set.cpp +++ b/example/doc_avl_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_avltree_algorithms.cpp b/example/doc_avltree_algorithms.cpp index ee2655c..71b22be 100644 --- a/example/doc_avltree_algorithms.cpp +++ b/example/doc_avltree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_bucket_traits.cpp b/example/doc_bucket_traits.cpp index 7663bf4..7fe1a89 100644 --- a/example/doc_bucket_traits.cpp +++ b/example/doc_bucket_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_clone_from.cpp b/example/doc_clone_from.cpp index ae3d8c9..f8c5794 100644 --- a/example/doc_clone_from.cpp +++ b/example/doc_clone_from.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_entity.cpp b/example/doc_entity.cpp index 70b109f..efdbc89 100644 --- a/example/doc_entity.cpp +++ b/example/doc_entity.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_erasing_and_disposing.cpp b/example/doc_erasing_and_disposing.cpp index cf0062d..f3bb51a 100644 --- a/example/doc_erasing_and_disposing.cpp +++ b/example/doc_erasing_and_disposing.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_external_value_traits.cpp b/example/doc_external_value_traits.cpp index b53817c..fe78703 100644 --- a/example/doc_external_value_traits.cpp +++ b/example/doc_external_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_how_to_use.cpp b/example/doc_how_to_use.cpp index 2951096..b966fe0 100644 --- a/example/doc_how_to_use.cpp +++ b/example/doc_how_to_use.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_iterator_from_value.cpp b/example/doc_iterator_from_value.cpp index 875db31..652e314 100644 --- a/example/doc_iterator_from_value.cpp +++ b/example/doc_iterator_from_value.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_list.cpp b/example/doc_list.cpp index a4ffcee..0f3818c 100644 --- a/example/doc_list.cpp +++ b/example/doc_list.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_list_algorithms.cpp b/example/doc_list_algorithms.cpp index c5ef4b4..45c1d2e 100644 --- a/example/doc_list_algorithms.cpp +++ b/example/doc_list_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_offset_ptr.cpp b/example/doc_offset_ptr.cpp index 9b88708..064ee6e 100644 --- a/example/doc_offset_ptr.cpp +++ b/example/doc_offset_ptr.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_positional_insertion.cpp b/example/doc_positional_insertion.cpp new file mode 100644 index 0000000..7609bc2 --- /dev/null +++ b/example/doc_positional_insertion.cpp @@ -0,0 +1,74 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2009-2009 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +//[doc_positional_insertion +#include +#include +#include +#include + +using namespace boost::intrusive; + +//A simple class with a set hook +class MyClass : public set_base_hook<> +{ + public: + int int_; + + MyClass(int i) : int_(i) {} + friend bool operator< (const MyClass &a, const MyClass &b) + { return a.int_ < b.int_; } + friend bool operator> (const MyClass &a, const MyClass &b) + { return a.int_ > b.int_; } +}; + +int main() +{ + //Create some ORDERED elements + std::vector values; + for(int i = 0; i < 100; ++i) values.push_back(MyClass(i)); + + { //Data is naturally ordered in the vector with the same criteria + //as multiset's comparison predicate, so we can just push back + //all elements, which is more efficient than normal insertion + multiset mset; + for(int i = 0; i < 100; ++i) mset.push_back(values[i]); + + //Now check orderd invariant + multiset::const_iterator next(mset.cbegin()), it(next++); + for(int i = 0; i < 99; ++i, ++it, ++next) assert(*it < *next); + } + { //Now the correct order for the set is the reverse order + //so let's push front all elements + multiset > > mset; + for(int i = 0; i < 100; ++i) mset.push_front(values[i]); + + //Now check orderd invariant + multiset > >:: + const_iterator next(mset.cbegin()), it(next++); + for(int i = 0; i < 99; ++i, ++it, ++next) assert(*it > *next); + } + { //Now push the first and the last and insert the rest + //before the last position using "insert_before" + multiset mset; + mset.insert_before(mset.begin(), values[0]); + multiset::const_iterator pos = + mset.insert_before(mset.end(), values[99]); + for(int i = 1; i < 99; ++i) mset.insert_before(pos, values[i]); + + //Now check orderd invariant + multiset::const_iterator next(mset.cbegin()), it(next++); + for(int i = 0; i < 99; ++i, ++it, ++next) assert(*it < *next); + } + + return 0; +} +//] diff --git a/example/doc_rbtree_algorithms.cpp b/example/doc_rbtree_algorithms.cpp index 0843365..d30dce7 100644 --- a/example/doc_rbtree_algorithms.cpp +++ b/example/doc_rbtree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_set.cpp b/example/doc_set.cpp index 49fbe9c..8dc501f 100644 --- a/example/doc_set.cpp +++ b/example/doc_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_sg_set.cpp b/example/doc_sg_set.cpp index 5885b0e..bf67ba7 100644 --- a/example/doc_sg_set.cpp +++ b/example/doc_sg_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_slist.cpp b/example/doc_slist.cpp index 42220b9..fb8bbeb 100644 --- a/example/doc_slist.cpp +++ b/example/doc_slist.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_slist_algorithms.cpp b/example/doc_slist_algorithms.cpp index 7e7f155..19f1d7b 100644 --- a/example/doc_slist_algorithms.cpp +++ b/example/doc_slist_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_splay_algorithms.cpp b/example/doc_splay_algorithms.cpp index f90a7e2..6b59396 100644 --- a/example/doc_splay_algorithms.cpp +++ b/example/doc_splay_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_splay_set.cpp b/example/doc_splay_set.cpp index 87ed7e0..be8dafa 100644 --- a/example/doc_splay_set.cpp +++ b/example/doc_splay_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_splaytree_algorithms.cpp b/example/doc_splaytree_algorithms.cpp index aeafaae..ed9f943 100644 --- a/example/doc_splaytree_algorithms.cpp +++ b/example/doc_splaytree_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_stateful_value_traits.cpp b/example/doc_stateful_value_traits.cpp index 4712387..696828b 100644 --- a/example/doc_stateful_value_traits.cpp +++ b/example/doc_stateful_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_treap_algorithms.cpp b/example/doc_treap_algorithms.cpp index 773aa69..4379f40 100644 --- a/example/doc_treap_algorithms.cpp +++ b/example/doc_treap_algorithms.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_treap_set.cpp b/example/doc_treap_set.cpp index 7ae4fec..79fd187 100644 --- a/example/doc_treap_set.cpp +++ b/example/doc_treap_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_unordered_set.cpp b/example/doc_unordered_set.cpp index a007919..fdd0938 100644 --- a/example/doc_unordered_set.cpp +++ b/example/doc_unordered_set.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_value_traits.cpp b/example/doc_value_traits.cpp index f9bb897..f13e1fe 100644 --- a/example/doc_value_traits.cpp +++ b/example/doc_value_traits.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/example/doc_window.cpp b/example/doc_window.cpp index f00f43b..f471c1e 100644 --- a/example/doc_window.cpp +++ b/example/doc_window.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/index.html b/index.html index de9100d..c3f8f9b 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ diff --git a/perf/perf_list.cpp b/perf/perf_list.cpp index ef73947..4f5d86e 100644 --- a/perf/perf_list.cpp +++ b/perf/perf_list.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index abe74de..8501d3b 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -243,12 +243,18 @@ + + + + @@ -382,6 +388,9 @@ + + diff --git a/proj/vc7ide/to-do.txt b/proj/vc7ide/to-do.txt index 534314c..6cda9e3 100644 --- a/proj/vc7ide/to-do.txt +++ b/proj/vc7ide/to-do.txt @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -9,20 +9,8 @@ // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// --> Implement C++0x features (variadic templates & rvalue references) +-> Implement C++0x features (rvalue references) -> Offer bidirectional iterator for hashtables -> Non-array buckets -> Document incremental<> option better - --> Revise treap's hooks should be restored if the operation throws --> Revise treap help to add priority changes (throw, new functions, etc.) --> Revise make_functions, and any hook tests to add missing containers --> On exceptions, auto_unlink/safe_link hooks default state should be recovered - (insert_equal, insert_lower_bound, insert_equal_upper_bound) --> insert_unique_check should also compare priorities. --> test insert_unique_check with hint in tests --> revise strong exception safety concepts for treap::erase functions. - What happens with range deletions? -> Assure stable order for optimize_multikey and inverse order otherwise --> linear slist's splice_after(..., slist &x) can be optimized if *this is empty --> optimize slist::merge like list::merge diff --git a/test/any_test.cpp b/test/any_test.cpp index bd2c955..6fc6a4c 100644 --- a/test/any_test.cpp +++ b/test/any_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/avl_multiset_test.cpp b/test/avl_multiset_test.cpp index bc8c7eb..5243ef4 100644 --- a/test/avl_multiset_test.cpp +++ b/test/avl_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -17,6 +17,26 @@ #include "smart_ptr.hpp" #include "generic_multiset_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +}}} + using namespace boost::intrusive; struct my_tag; diff --git a/test/avl_set_test.cpp b/test/avl_set_test.cpp index 8b4f16e..cd76006 100644 --- a/test/avl_set_test.cpp +++ b/test/avl_set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +16,27 @@ #include "smart_ptr.hpp" #include "generic_set_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +}}} + + using namespace boost::intrusive; struct my_tag; diff --git a/test/common_functors.hpp b/test/common_functors.hpp index db52197..ebfc846 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/custom_bucket_traits_test.cpp b/test/custom_bucket_traits_test.cpp index a74eb0b..c2e1d7c 100644 --- a/test/custom_bucket_traits_test.cpp +++ b/test/custom_bucket_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/default_hook_test.cpp b/test/default_hook_test.cpp index 55c31a2..aef7fa8 100644 --- a/test/default_hook_test.cpp +++ b/test/default_hook_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/external_value_traits_test.cpp b/test/external_value_traits_test.cpp index ec70f13..5016697 100644 --- a/test/external_value_traits_test.cpp +++ b/test/external_value_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 9f39ff7..ea8db49 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -35,6 +35,12 @@ struct has_rebalance static const bool value = false; }; +template +struct has_insert_before +{ + static const bool value = false; +}; + template class ContainerDefiner> struct test_generic_assoc { @@ -52,6 +58,9 @@ struct test_generic_assoc static void test_rebalance(std::vector& values); static void test_rebalance(std::vector& values, boost::intrusive::detail::true_type); static void test_rebalance(std::vector& values, boost::intrusive::detail::false_type); + static void test_insert_before(std::vector& values); + static void test_insert_before(std::vector& values, boost::intrusive::detail::true_type); + static void test_insert_before(std::vector& values, boost::intrusive::detail::false_type); static void test_container_from_iterator(std::vector& values); }; @@ -149,6 +158,7 @@ void test_generic_assoc::test_all(std::vector::test_rebalance test_rebalance(values, enabler()); } +template class ContainerDefiner> +void test_generic_assoc::test_insert_before +(std::vector& values, boost::intrusive::detail::true_type) +{ + typedef typename ValueTraits::value_type value_type; + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type assoc_type; + { + assoc_type testset; + typedef typename std::vector::iterator vec_iterator; + for(vec_iterator it(values.begin()), itend(values.end()) + ; it != itend + ; ++it){ + testset.push_back(*it); + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } + { + assoc_type testset; + typedef typename std::vector::iterator vec_iterator; + for(vec_iterator it(--values.end()), itend(--values.begin()) + ; it != itend + ; --it){ + testset.push_front(*it); + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } + { + assoc_type testset; + typedef typename std::vector::iterator vec_iterator; + typename assoc_type::iterator it_pos = + testset.insert_before(testset.end(), *values.rbegin()); + testset.insert_before(testset.begin(), *values.begin()); + for(vec_iterator it(++values.begin()), itend(--values.end()) + ; it != itend + ; ++it){ + testset.insert_before(it_pos, *it); + } + BOOST_TEST(testset.size() == values.size()); + TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); + } +} + +template class ContainerDefiner> +void test_generic_assoc::test_insert_before +(std::vector&, boost::intrusive::detail::false_type) +{} + +template class ContainerDefiner> +void test_generic_assoc::test_insert_before +(std::vector& values) +{ + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type assoc_type; + typedef typename detail::remove_const::type Type; + typedef detail::bool_::value> enabler; + test_insert_before(values, enabler()); +} + }}} //namespace boost::intrusive::test #include diff --git a/test/generic_multiset_test.hpp b/test/generic_multiset_test.hpp index 21aeb3c..4cd2e7a 100644 --- a/test/generic_multiset_test.hpp +++ b/test/generic_multiset_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/generic_set_test.hpp b/test/generic_set_test.hpp index 5df2489..5edde5f 100644 --- a/test/generic_set_test.hpp +++ b/test/generic_set_test.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,12 @@ namespace boost{ namespace intrusive{ namespace test{ +template +struct is_treap +{ + static const bool value = false; +}; + template class ContainerDefiner> struct test_generic_set { @@ -30,6 +36,9 @@ struct test_generic_set static void test_all(); static void test_sort(std::vector& values); static void test_insert(std::vector& values); + static void test_insert_advanced(std::vector& values, boost::intrusive::detail::true_type); + static void test_insert_advanced(std::vector& values, boost::intrusive::detail::false_type); + static void test_insert_advanced(std::vector& values); static void test_swap(std::vector& values); static void test_find(std::vector& values); static void test_impl(); @@ -65,6 +74,7 @@ void test_generic_set::test_all() } test_sort(values); test_insert(values); + test_insert_advanced(values); test_swap(values); test_find(values); test_impl(); @@ -139,32 +149,94 @@ void test_generic_set::test_insert(std::vector , constant_time_size >::type set_type; - set_type testset; - testset.insert(&values[0] + 2, &values[0] + 5); + { + set_type testset; + testset.insert(&values[0] + 2, &values[0] + 5); - const set_type& const_testset = testset; - { int init_values [] = { 1, 4, 5 }; - TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); } + const set_type& const_testset = testset; + { int init_values [] = { 1, 4, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, const_testset.begin() ); } - typename set_type::iterator i = testset.begin(); - BOOST_TEST (i->value_ == 1); + typename set_type::iterator i = testset.begin(); + BOOST_TEST (i->value_ == 1); - i = testset.insert (i, values[0]); - BOOST_TEST (&*i == &values[0]); + i = testset.insert (i, values[0]); + BOOST_TEST (&*i == &values[0]); - { int init_values [] = { 5, 4, 3, 1 }; - TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); } + { int init_values [] = { 5, 4, 3, 1 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.rbegin() ); } - i = testset.iterator_to (values[2]); - BOOST_TEST (&*i == &values[2]); + i = testset.iterator_to (values[2]); + BOOST_TEST (&*i == &values[2]); - i = set_type::s_iterator_to(values[2]); - BOOST_TEST (&*i == &values[2]); + i = set_type::s_iterator_to(values[2]); + BOOST_TEST (&*i == &values[2]); + + testset.erase (i); + { int init_values [] = { 1, 3, 5 }; + TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } + } +} + +template class ContainerDefiner> +void test_generic_set::test_insert_advanced +(std::vector& values, boost::intrusive::detail::true_type) +{ + typedef typename ValueTraits::value_type value_type; + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type set_type; + { + set_type testset; + testset.insert(&values[0], &values[0] + values.size()); + value_type v(1); + typename set_type::insert_commit_data data; + BOOST_TEST (!testset.insert_check(v, testset.value_comp(), testset.priority_comp(), data).second); + BOOST_TEST (!testset.insert_check(testset.begin(), v, testset.value_comp(), testset.priority_comp(), data).second); + } +} + + +template class ContainerDefiner> +void test_generic_set::test_insert_advanced +(std::vector& values) +{ + typedef typename ValueTraits::value_type value_type; + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type set_type; + typedef typename detail::remove_const::type Type; + typedef detail::bool_::value> enabler; + test_insert_advanced(values, enabler()); +} + + +//test: insert, const_iterator, const_reverse_iterator, erase, s_iterator_to: +template class ContainerDefiner> +void test_generic_set::test_insert_advanced + ( std::vector& values + , boost::intrusive::detail::false_type) +{ + typedef typename ValueTraits::value_type value_type; + typedef typename ContainerDefiner + < value_type + , value_traits + , constant_time_size + >::type set_type; + { + set_type testset; + testset.insert(&values[0], &values[0] + values.size()); + value_type v(1); + typename set_type::insert_commit_data data; + BOOST_TEST (!testset.insert_check(v, testset.value_comp(), data).second); + BOOST_TEST (!testset.insert_check(testset.begin(), v, testset.value_comp(), data).second); + } +} - testset.erase (i); - { int init_values [] = { 1, 3, 5 }; - TEST_INTRUSIVE_SEQUENCE( init_values, testset.begin() ); } -} //test: insert (seq-version), swap, erase (seq-version), size: template class ContainerDefiner> diff --git a/test/itestvalue.hpp b/test/itestvalue.hpp index a2885db..e0105f9 100644 --- a/test/itestvalue.hpp +++ b/test/itestvalue.hpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -115,12 +115,13 @@ std::size_t hash_value(const testvalue &t) } template -bool priority_order(const testvalue &t1, const testvalue &t2) +bool priority_order( const testvalue &t1 + , const testvalue &t2) { std::size_t hash1 = hash_value(t1); - boost::hash_combine(hash1,&t1); + boost::hash_combine(hash1, &t1); std::size_t hash2 = hash_value(t2); - boost::hash_combine(hash2,&t2); + boost::hash_combine(hash2, &t2); return hash1 < hash2; } @@ -150,6 +151,31 @@ struct is_even (const testvalue& v1) const { return (v1.value_ & 1) == 0; } }; +/* +struct int_testvalue_comp +{ + template + bool operator() + (const testvalue& v1, const int &i) const + { return v1.value_ < i; } + template + bool operator() + (const int &i, const testvalue& v1) const + { return i < v1.value_; } +}; + +struct int_testvalue_pcomp +{ + template + bool operator() + (const testvalue& v1, const int &i) const + { return v1.value_ < i; } + template + bool operator() + (const int &i, const testvalue& v1) const + { return i < v1.value_; } +}; +*/ } //namespace boost{ } //namespace intrusive{ diff --git a/test/list_test.cpp b/test/list_test.cpp index 8e67f8b..e9f8b74 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/make_functions_test.cpp b/test/make_functions_test.cpp index 2f8e1aa..e98b5fc 100644 --- a/test/make_functions_test.cpp +++ b/test/make_functions_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/multiset_test.cpp b/test/multiset_test.cpp index 6bb0b06..6cd3bc2 100644 --- a/test/multiset_test.cpp +++ b/test/multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +16,26 @@ #include "smart_ptr.hpp" #include "generic_multiset_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +}}} + using namespace boost::intrusive; struct my_tag; diff --git a/test/set_test.cpp b/test/set_test.cpp index 6d28424..aa1ca2b 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -11,11 +11,32 @@ // ///////////////////////////////////////////////////////////////////////////// #include + #include #include "itestvalue.hpp" #include "smart_ptr.hpp" #include "generic_set_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +}}} + struct my_tag; using namespace boost::intrusive; @@ -134,4 +155,5 @@ int main( int, char* [] ) test_main_template, true>()(); return boost::report_errors(); } + #include diff --git a/test/sg_multiset_test.cpp b/test/sg_multiset_test.cpp index 327eaf0..ae5eb41 100644 --- a/test/sg_multiset_test.cpp +++ b/test/sg_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -34,6 +34,23 @@ struct has_rebalance +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + }}} using namespace boost::intrusive; diff --git a/test/sg_set_test.cpp b/test/sg_set_test.cpp index 61c19a4..1d49081 100644 --- a/test/sg_set_test.cpp +++ b/test/sg_set_test.cpp @@ -33,6 +33,22 @@ struct has_rebalance +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + }}} diff --git a/test/slist_test.cpp b/test/slist_test.cpp index ff0bd7f..57587c3 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/splay_multiset_test.cpp b/test/splay_multiset_test.cpp index 21bd600..407c86c 100644 --- a/test/splay_multiset_test.cpp +++ b/test/splay_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/stateful_value_traits_test.cpp b/test/stateful_value_traits_test.cpp index ffba752..46867ae 100644 --- a/test/stateful_value_traits_test.cpp +++ b/test/stateful_value_traits_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/test_container.hpp b/test/test_container.hpp index b3124e9..c900a6b 100644 --- a/test/test_container.hpp +++ b/test/test_container.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -20,6 +20,12 @@ namespace boost { namespace intrusive { namespace test { +template +struct is_unordered +{ + static const bool value = false; +}; + template struct has_const_overloads { @@ -78,6 +84,7 @@ void test_sequence_container(Container & c, Data & d) BOOST_TEST( c.size() == 0 ); BOOST_TEST( c.empty() ); + { typename Data::iterator i = d.begin(); c.insert( c.begin(), *i ); @@ -87,7 +94,8 @@ void test_sequence_container(Container & c, Data & d) BOOST_TEST( c.size() == 2 ); BOOST_TEST( !c.empty() ); - c.erase( c.begin() ); + typename Container::iterator i; + i = c.erase( c.begin() ); BOOST_TEST( c.size() == 1 ); @@ -97,7 +105,8 @@ void test_sequence_container(Container & c, Data & d) c.insert( c.begin(), *(i) ); } - c.erase( c.begin(), c.end() ); + i = c.erase( c.begin(), c.end() ); + BOOST_TEST( i == c.end() ); BOOST_TEST( c.empty() ); @@ -107,7 +116,8 @@ void test_sequence_container(Container & c, Data & d) BOOST_TEST( c.begin() != c.end() ); - c.erase( c.begin() ); + i = c.erase_and_dispose( c.begin(), detail::null_disposer() ); + BOOST_TEST( i == c.begin() ); c.assign(d.begin(), d.end()); @@ -119,9 +129,90 @@ void test_sequence_container(Container & c, Data & d) BOOST_TEST( c.empty() ); } +template< class Container, class Data > +void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::true_ unordered) +{ + (void)unordered; + typedef typename Container::size_type size_type; + + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(), d.end()); + + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_TEST( c.find(*di) != c.end() ); + } + + typename Data::const_iterator db = d.begin(); + typename Data::const_iterator da = db++; + + size_type old_size = c.size(); + + c.erase(*da, c.hash_function(), c.key_eq()); + BOOST_TEST( c.size() == old_size-1 ); + //This should not eras anyone + size_type second_erase = c.erase_and_dispose + ( *da, c.hash_function(), c.key_eq(), detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); + + BOOST_TEST( c.count(*da, c.hash_function(), c.key_eq()) == 0 ); + BOOST_TEST( c.count(*db, c.hash_function(), c.key_eq()) != 0 ); + + BOOST_TEST( c.find(*da, c.hash_function(), c.key_eq()) == c.end() ); + BOOST_TEST( c.find(*db, c.hash_function(), c.key_eq()) != c.end() ); + + BOOST_TEST( c.equal_range(*db, c.hash_function(), c.key_eq()).first != c.end() ); + + c.clear(); + + BOOST_TEST( c.equal_range(*da, c.hash_function(), c.key_eq()).first == c.end() ); +} + +template< class Container, class Data > +void test_common_unordered_and_associative_container(Container & c, Data & d, boost::intrusive::detail::false_ unordered) +{ + (void)unordered; + typedef typename Container::size_type size_type; + + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(), d.end()); + + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_TEST( c.find(*di, c.key_comp()) != c.end() ); + } + + typename Data::const_iterator db = d.begin(); + typename Data::const_iterator da = db++; + + size_type old_size = c.size(); + + c.erase(*da, c.key_comp()); + BOOST_TEST( c.size() == old_size-1 ); + //This should not eras anyone + size_type second_erase = c.erase_and_dispose( *da, c.key_comp(), detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); + + BOOST_TEST( c.count(*da, c.key_comp()) == 0 ); + BOOST_TEST( c.count(*db, c.key_comp()) != 0 ); + BOOST_TEST( c.find(*da, c.key_comp()) == c.end() ); + BOOST_TEST( c.find(*db, c.key_comp()) != c.end() ); + BOOST_TEST( c.equal_range(*db, c.key_comp()).first != c.end() ); + c.clear(); + BOOST_TEST( c.equal_range(*da, c.key_comp()).first == c.end() ); +} + + template< class Container, class Data > void test_common_unordered_and_associative_container(Container & c, Data & d) { + { typedef typename Container::size_type size_type; assert( d.size() > 2 ); @@ -141,8 +232,10 @@ void test_common_unordered_and_associative_container(Container & c, Data & d) size_type old_size = c.size(); c.erase(*da); - BOOST_TEST( c.size() == old_size-1 ); + //This should not eras anyone + size_type second_erase = c.erase_and_dispose( *da, detail::null_disposer() ); + BOOST_TEST( second_erase == 0 ); BOOST_TEST( c.count(*da) == 0 ); BOOST_TEST( c.count(*db) != 0 ); @@ -155,6 +248,9 @@ void test_common_unordered_and_associative_container(Container & c, Data & d) c.clear(); BOOST_TEST( c.equal_range(*da).first == c.end() ); + } + typedef detail::bool_::value> enabler; + test_common_unordered_and_associative_container(c, d, enabler()); } template< class Container, class Data > diff --git a/test/test_macros.hpp b/test/test_macros.hpp index 0b23322..f5a3b62 100644 --- a/test/test_macros.hpp +++ b/test/test_macros.hpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Ion Gaztanaga 2006-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/test/treap_multiset_test.cpp b/test/treap_multiset_test.cpp index dbae120..ced326b 100644 --- a/test/treap_multiset_test.cpp +++ b/test/treap_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -17,6 +17,26 @@ #include "smart_ptr.hpp" #include "generic_multiset_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +}}} + using namespace boost::intrusive; struct my_tag; diff --git a/test/treap_set_test.cpp b/test/treap_set_test.cpp index cbd6471..87d7ae6 100644 --- a/test/treap_set_test.cpp +++ b/test/treap_set_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -15,6 +15,43 @@ #include "smart_ptr.hpp" #include "generic_set_test.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct has_insert_before > +{ + static const bool value = true; +}; + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct is_treap > +{ + static const bool value = true; +}; + +}}} + + using namespace boost::intrusive; struct my_tag; diff --git a/test/unordered_multiset_test.cpp b/test/unordered_multiset_test.cpp index 206605d..7d1e8da 100644 --- a/test/unordered_multiset_test.cpp +++ b/test/unordered_multiset_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,26 @@ #include "test_macros.hpp" #include "test_container.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct is_unordered > +{ + static const bool value = true; +}; + +}}} + using namespace boost::intrusive; struct my_tag; diff --git a/test/unordered_set_test.cpp b/test/unordered_set_test.cpp index f6b5e48..ee65896 100644 --- a/test/unordered_set_test.cpp +++ b/test/unordered_set_test.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. -// (C) Copyright Ion Gaztanaga 2006-2008. +// (C) Copyright Ion Gaztanaga 2006-2009. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -22,6 +22,26 @@ #include "test_macros.hpp" #include "test_container.hpp" +namespace boost { namespace intrusive { namespace test { + +#if !defined (BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct is_unordered > +{ + static const bool value = true; +}; + +}}} + using namespace boost::intrusive; struct my_tag; diff --git a/test/virtual_base_test.cpp b/test/virtual_base_test.cpp index 92a700b..dabef96 100644 --- a/test/virtual_base_test.cpp +++ b/test/virtual_base_test.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2008 +// (C) Copyright Ion Gaztanaga 2007-2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at From c3b42d233c4b5427f124558386e9945d509d894d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 16 Oct 2009 14:54:47 +0000 Subject: [PATCH 15/29] Fixes for 1.41 [SVN r56919] --- test/smart_ptr.hpp | 102 ++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index 70e4371..24ac8bb 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -35,8 +35,8 @@ struct empty_type{}; template struct random_it -: public boost::iterator +: public boost::iterator { typedef const T* const_pointer; typedef const T& const_reference; @@ -108,25 +108,25 @@ class smart_ptr public: //Public Functions //!Constructor from raw pointer (allows "0" pointer conversion). Never throws. - smart_ptr(pointer ptr = 0) + explicit smart_ptr(pointer ptr = 0) : m_ptr(ptr) {} //!Constructor from other pointer. Never throws. template - smart_ptr(T *ptr) + smart_ptr(T *ptr) : m_ptr(ptr) {} - //!Constructor from other smart_ptr + //!Constructor from other smart_ptr smart_ptr(const smart_ptr& ptr) : m_ptr(ptr.m_ptr) {} - //!Constructor from other smart_ptr. If pointers of pointee types are + //!Constructor from other smart_ptr. If pointers of pointee types are //!convertible, offset_ptrs will be convertibles. Never throws. template - smart_ptr(const smart_ptr &ptr) + smart_ptr(const smart_ptr &ptr) : m_ptr(ptr.m_ptr) {} @@ -159,16 +159,16 @@ class smart_ptr { return m_ptr; } //!Pointer-like -> operator. It can return 0 pointer. Never throws. - pointer operator->() const + pointer operator->() const { return this->get(); } - //!Dereferencing operator, if it is a null smart_ptr behavior + //!Dereferencing operator, if it is a null smart_ptr behavior //! is undefined. Never throws. - reference operator* () const + reference operator* () const { return *(this->get()); } //!Indexing operator. Never throws. - reference operator[](std::ptrdiff_t idx) const + reference operator[](std::ptrdiff_t idx) const { return this->get()[idx]; } //!Assignment from pointer (saves extra conversion). Never throws. @@ -179,18 +179,18 @@ class smart_ptr smart_ptr& operator= (const smart_ptr & pt) { m_ptr = pt.m_ptr; return *this; } - //!Assignment from related smart_ptr. If pointers of pointee types + //!Assignment from related smart_ptr. If pointers of pointee types //! are assignable, offset_ptrs will be assignable. Never throws. template smart_ptr& operator= (const smart_ptr & pt) { m_ptr = pt.m_ptr; return *this; } - + //!smart_ptr + std::ptrdiff_t. Never throws. - smart_ptr operator+ (std::ptrdiff_t offset) const + smart_ptr operator+ (std::ptrdiff_t offset) const { return smart_ptr(this->get()+offset); } //!smart_ptr - std::ptrdiff_t. Never throws. - smart_ptr operator- (std::ptrdiff_t offset) const + smart_ptr operator- (std::ptrdiff_t offset) const { return smart_ptr(this->get()-offset); } //!smart_ptr += std::ptrdiff_t. Never throws. @@ -202,7 +202,7 @@ class smart_ptr { m_ptr -= offset; return *this; } //!++smart_ptr. Never throws. - smart_ptr& operator++ (void) + smart_ptr& operator++ (void) { ++m_ptr; return *this; } //!smart_ptr++. Never throws. @@ -210,7 +210,7 @@ class smart_ptr { smart_ptr temp(*this); ++*this; return temp; } //!--smart_ptr. Never throws. - smart_ptr& operator-- (void) + smart_ptr& operator-- (void) { --m_ptr; return *this; } //!smart_ptr--. Never throws. @@ -218,16 +218,16 @@ class smart_ptr { smart_ptr temp(*this); --*this; return temp; } //!safe bool conversion operator. Never throws. - operator unspecified_bool_type() const + operator unspecified_bool_type() const { return this->get()? &self_t::unspecified_bool_type_func : 0; } - //!Not operator. Not needed in theory, but improves portability. + //!Not operator. Not needed in theory, but improves portability. //!Never throws. bool operator! () const { return this->get() == 0; } /* friend void swap (smart_ptr &pt, smart_ptr &pt2) - { + { value_type *ptr = pt.get(); pt = pt2; pt2 = ptr; @@ -237,67 +237,67 @@ class smart_ptr //!smart_ptr == smart_ptr. Never throws. template -inline bool operator== (const smart_ptr &pt1, +inline bool operator== (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() == pt2.get(); } //!smart_ptr != smart_ptr. Never throws. template -inline bool operator!= (const smart_ptr &pt1, +inline bool operator!= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() != pt2.get(); } //!smart_ptr < smart_ptr. Never throws. template -inline bool operator< (const smart_ptr &pt1, +inline bool operator< (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() < pt2.get(); } //!smart_ptr <= smart_ptr. Never throws. template -inline bool operator<= (const smart_ptr &pt1, +inline bool operator<= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() <= pt2.get(); } //!smart_ptr > smart_ptr. Never throws. template -inline bool operator> (const smart_ptr &pt1, +inline bool operator> (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() > pt2.get(); } //!smart_ptr >= smart_ptr. Never throws. template -inline bool operator>= (const smart_ptr &pt1, +inline bool operator>= (const smart_ptr &pt1, const smart_ptr &pt2) { return pt1.get() >= pt2.get(); } -//!operator<< -template -inline std::basic_ostream & operator<< +//!operator<< +template +inline std::basic_ostream & operator<< (std::basic_ostream & os, smart_ptr const & p) { return os << p.get(); } -//!operator>> -template -inline std::basic_istream & operator>> +//!operator>> +template +inline std::basic_istream & operator>> (std::basic_istream & os, smart_ptr & p) { Y * tmp; return os >> tmp; p = tmp; } -//!std::ptrdiff_t + smart_ptr +//!std::ptrdiff_t + smart_ptr template inline smart_ptr operator+(std::ptrdiff_t diff, const smart_ptr& right) { return right + diff; } -//!smart_ptr - smart_ptr +//!smart_ptr - smart_ptr template inline std::ptrdiff_t operator- (const smart_ptr &pt, const smart_ptr &pt2) { return pt.get()- pt2.get(); } -//!swap specialization +//!swap specialization template -inline void swap (smart_ptr &pt, +inline void swap (smart_ptr &pt, smart_ptr &pt2) -{ +{ typename smart_ptr::value_type *ptr = pt.get(); pt = pt2; pt2 = ptr; @@ -310,35 +310,35 @@ inline T* get_pointer(const smart_ptr & p) { return p.get(); } //!Simulation of static_cast between pointers. Never throws. -template -inline smart_ptr +template +inline smart_ptr static_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::static_cast_tag()); +{ + return smart_ptr(r, detail::static_cast_tag()); } //!Simulation of const_cast between pointers. Never throws. -template +template inline smart_ptrconst_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::const_cast_tag()); +{ + return smart_ptr(r, detail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. Never throws. -template -inline smart_ptr +template +inline smart_ptr dynamic_pointer_cast(smart_ptr const & r) -{ +{ return smart_ptr - (r, detail::dynamic_cast_tag()); + (r, detail::dynamic_cast_tag()); } //!Simulation of reinterpret_cast between pointers. Never throws. -template +template inline smart_ptr reinterpret_pointer_cast(smart_ptr const & r) -{ - return smart_ptr(r, detail::reinterpret_cast_tag()); +{ + return smart_ptr(r, detail::reinterpret_cast_tag()); } } //namespace intrusive { From 18347ffe415d9f8f3c45f581d6bc5b0711a831f0 Mon Sep 17 00:00:00 2001 From: "Troy D. Straszheim" Date: Sat, 17 Oct 2009 02:07:38 +0000 Subject: [PATCH 16/29] rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back [SVN r56942] --- CMakeLists.txt | 22 ---------------------- module.cmake | 1 - 2 files changed, 23 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 module.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 73434d8..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -#---------------------------------------------------------------------------- -# This file was automatically generated from the original CMakeLists.txt file -# Add a variable to hold the headers for the library -set (lib_headers - intrusive_ptr.hpp - intrusive -) - -# Add a library target to the build system -boost_library_project( - intrusive - # SRCDIRS - # TESTDIRS - HEADERS ${lib_headers} - # DOCDIRS - # DESCRIPTION - MODULARIZED - # AUTHORS - # MAINTAINERS -) - - diff --git a/module.cmake b/module.cmake deleted file mode 100644 index edc114f..0000000 --- a/module.cmake +++ /dev/null @@ -1 +0,0 @@ -boost_module(intrusive DEPENDS utility) \ No newline at end of file From ec8cd592add8fb000a49959074c432b833d751b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 17 Oct 2009 15:23:57 +0000 Subject: [PATCH 17/29] Fixes for 1.41 [SVN r56955] --- include/boost/intrusive/detail/utilities.hpp | 2 +- include/boost/intrusive/list.hpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index 7846716..c548911 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -569,7 +569,7 @@ struct store_cont_ptr_on_it_impl template struct store_cont_ptr_on_it_impl { - static const bool value = false; + static const bool value = true; }; template diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 2cf3fed..965baa7 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -107,7 +107,6 @@ class list_impl static const bool constant_time_size = Config::constant_time_size; static const bool stateful_value_traits = detail::is_stateful_value_traits::value; - BOOST_STATIC_ASSERT(( stateful_value_traits == false )); /// @cond From 2a8980d24c72b60cb4bb5522a133c1372f1d218d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 17 Oct 2009 15:24:38 +0000 Subject: [PATCH 18/29] Fixes for 1.41 [SVN r56957] --- test/generic_assoc_test.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index ea8db49..50931c0 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -399,10 +399,12 @@ void test_generic_assoc::test_insert_before { assoc_type testset; typedef typename std::vector::iterator vec_iterator; - for(vec_iterator it(--values.end()), itend(--values.begin()) - ; it != itend - ; --it){ + + for(vec_iterator it(--values.end()); true; --it){ testset.push_front(*it); + if(it == values.begin()){ + break; + } } BOOST_TEST(testset.size() == values.size()); TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); From 91a969b910a272656a0c59b0c20b64d89acd6804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 19 Oct 2009 18:59:44 +0000 Subject: [PATCH 19/29] Fixes for 1.41 [SVN r57001] --- .../detail/is_stateful_value_traits.hpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/boost/intrusive/detail/is_stateful_value_traits.hpp b/include/boost/intrusive/detail/is_stateful_value_traits.hpp index a11f988..e38f4de 100644 --- a/include/boost/intrusive/detail/is_stateful_value_traits.hpp +++ b/include/boost/intrusive/detail/is_stateful_value_traits.hpp @@ -14,6 +14,25 @@ #define BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP #include + +#if defined(_MSC_VER) && (_MSC_VER <= 1310) + +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct is_stateful_value_traits +{ + static const bool value = !detail::is_empty_class::value; +}; + +}}} + +#else + #include BOOST_INTRUSIVE_CREATE_FUNCTION_DETECTOR(to_node_ptr, boost_intrusive) @@ -51,6 +70,8 @@ struct is_stateful_value_traits }}} +#endif + #include #endif //@ifndef BOOST_INTRUSIVE_DETAIL_IS_STATEFUL_VALUE_TRAITS_HPP From 601361edd9ad27ab16cfbd3f3667d7fb78131d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 19 Oct 2009 19:02:22 +0000 Subject: [PATCH 20/29] Fixes for 1.41 [SVN r57003] --- doc/intrusive.qbk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index c37883a..4c14d1c 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -3183,7 +3183,8 @@ Until now all shown custom value traits are stateless, that is, [*the transforma and values is implemented in terms of static functions]. It's possible to use [*stateful] value traits so that we can separate nodes and values and [*avoid modifying types to insert nodes]. [*Boost.Intrusive] differentiates between stateful and stateless value traits by checking if all -Node <-> Value transformation functions are static or not: +Node <-> Value transformation functions are static or not (except for Visual 7.1, since overloaded +static function detection is not possible, in this case the implementation checks if the class is empty): * If all Node <-> Value transformation functions are static , a [*stateless] value traits is assumed. transformations must be static functions. From 327c9cab8d526ff2647a995c1b7f7bf0e169e65b Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 24 Oct 2009 17:46:45 +0000 Subject: [PATCH 21/29] Fixed compilation problem with Intel compiler. [SVN r57138] --- include/boost/intrusive/derivation_value_traits.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 88edeab..7b5b013 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -47,7 +47,7 @@ struct derivation_value_traits { return pointer(static_cast(detail::get_pointer(n))); } static const_pointer to_value_ptr(const_node_ptr n) - { return const_pointer(static_cast(detail::get_pointer(n))); } + { return const_pointer(static_cast(detail::get_pointer(n))); } }; } //namespace intrusive From 90d4ec52892d649c96f4a92d1c2e8557b6b3a8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 12 Mar 2010 13:18:29 +0000 Subject: [PATCH 22/29] Interprocess: [@https://svn.boost.org/trac/boost/ticket/3439 #3439], [@https://svn.boost.org/trac/boost/ticket/3846 #3846], [@https://svn.boost.org/trac/boost/ticket/3947 #3947], [@https://svn.boost.org/trac/boost/ticket/3985 #3985]. Intrusive: [@https://svn.boost.org/trac/boost/ticket/3668 #3668], [@https://svn.boost.org/trac/boost/ticket/3339 #3688], [@https://svn.boost.org/trac/boost/ticket/3698 #3698], [@https://svn.boost.org/trac/boost/ticket/3706 #3706], [@https://svn.boost.org/trac/boost/ticket/3721 #3721]. [@https://svn.boost.org/trac/boost/ticket/3729 #3729], [@https://svn.boost.org/trac/boost/ticket/3746 #3746], [@https://svn.boost.org/trac/boost/ticket/3781 #3781], [@https://svn.boost.org/trac/boost/ticket/3829 #3829], [@https://svn.boost.org/trac/boost/ticket/3840 #3840], [@https://svn.boost.org/trac/boost/ticket/3339 #3339], [@https://svn.boost.org/trac/boost/ticket/3419 #3419], [@https://svn.boost.org/trac/boost/ticket/3431 #3431], [SVN r60514] --- include/boost/intrusive/avl_set.hpp | 4 ++ include/boost/intrusive/avltree.hpp | 6 +- .../boost/intrusive/avltree_algorithms.hpp | 2 +- .../intrusive/derivation_value_traits.hpp | 4 +- .../boost/intrusive/detail/hashtable_node.hpp | 9 +-- include/boost/intrusive/detail/list_node.hpp | 24 +++---- include/boost/intrusive/detail/slist_node.hpp | 24 +++---- .../intrusive/detail/tree_algorithms.hpp | 4 +- include/boost/intrusive/detail/tree_node.hpp | 25 +++---- include/boost/intrusive/detail/utilities.hpp | 68 +++++++++++++++++-- include/boost/intrusive/hashtable.hpp | 38 +++++------ include/boost/intrusive/list.hpp | 27 ++++++-- .../boost/intrusive/member_value_traits.hpp | 4 +- include/boost/intrusive/rbtree.hpp | 27 ++++++-- include/boost/intrusive/rbtree_algorithms.hpp | 2 +- include/boost/intrusive/set.hpp | 23 ++++++- include/boost/intrusive/sgtree.hpp | 4 +- include/boost/intrusive/sgtree_algorithms.hpp | 2 +- include/boost/intrusive/slist.hpp | 36 +++++++--- include/boost/intrusive/splay_set.hpp | 4 ++ include/boost/intrusive/splaytree.hpp | 4 +- .../boost/intrusive/splaytree_algorithms.hpp | 2 +- include/boost/intrusive/treap.hpp | 6 +- include/boost/intrusive/treap_algorithms.hpp | 2 +- include/boost/intrusive/treap_set.hpp | 4 ++ include/boost/intrusive/unordered_set.hpp | 40 +++++------ 26 files changed, 260 insertions(+), 135 deletions(-) diff --git a/include/boost/intrusive/avl_set.hpp b/include/boost/intrusive/avl_set.hpp index a944077..1c13c62 100644 --- a/include/boost/intrusive/avl_set.hpp +++ b/include/boost/intrusive/avl_set.hpp @@ -74,6 +74,8 @@ class avl_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; @@ -1264,6 +1266,8 @@ class avl_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; diff --git a/include/boost/intrusive/avltree.hpp b/include/boost/intrusive/avltree.hpp index e65f182..4b6e089 100644 --- a/include/boost/intrusive/avltree.hpp +++ b/include/boost/intrusive/avltree.hpp @@ -113,7 +113,7 @@ class avltree_impl ::type node_ptr; typedef typename boost::pointer_to_other ::type const_node_ptr; - typedef avltree_algorithms node_algorithms; + typedef avltree_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::value; @@ -167,7 +167,7 @@ class avltree_impl static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(detail::get_pointer(ptr))); + return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } size_traits &priv_size_traits() @@ -1398,7 +1398,7 @@ class avltree_impl static avltree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { header_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); node_plus_pred_t *n = detail::parent_from_member (r, &node_plus_pred_t::header_plus_size_); data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); diff --git a/include/boost/intrusive/avltree_algorithms.hpp b/include/boost/intrusive/avltree_algorithms.hpp index a632581..7e0cd2e 100644 --- a/include/boost/intrusive/avltree_algorithms.hpp +++ b/include/boost/intrusive/avltree_algorithms.hpp @@ -104,7 +104,7 @@ class avltree_algorithms static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); } /// @endcond diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 7b5b013..6ae28a3 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -44,10 +44,10 @@ struct derivation_value_traits { return node_ptr(&value); } static pointer to_value_ptr(node_ptr n) - { return pointer(static_cast(detail::get_pointer(n))); } + { return pointer(static_cast(detail::boost_intrusive_get_pointer(n))); } static const_pointer to_value_ptr(const_node_ptr n) - { return const_pointer(static_cast(detail::get_pointer(n))); } + { return const_pointer(static_cast(detail::boost_intrusive_get_pointer(n))); } }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index 1676b1c..a077155 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -36,6 +36,7 @@ struct prime_list_holder template const std::size_t prime_list_holder::prime_list[] = { + 3ul, 7ul, 11ul, 17ul, 29ul, 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, @@ -164,10 +165,10 @@ class hashtable_iterator { return *this->operator ->(); } pointer operator->() const - { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } + { return detail::boost_intrusive_get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } const Container *get_container() const - { return detail::get_pointer(cont_); } + { return detail::boost_intrusive_get_pointer(cont_); } const real_value_traits *get_real_value_traits() const { return &this->get_container()->get_real_value_traits(); } @@ -175,8 +176,8 @@ class hashtable_iterator private: void increment() { - const Container *cont = detail::get_pointer(cont_); - bucket_type* buckets = detail::get_pointer(cont->bucket_pointer()); + const Container *cont = detail::boost_intrusive_get_pointer(cont_); + bucket_type* buckets = detail::boost_intrusive_get_pointer(cont->bucket_pointer()); size_type buckets_len = cont->bucket_count(); ++slist_it_; diff --git a/include/boost/intrusive/detail/list_node.hpp b/include/boost/intrusive/detail/list_node.hpp index 935c522..e5df150 100644 --- a/include/boost/intrusive/detail/list_node.hpp +++ b/include/boost/intrusive/detail/list_node.hpp @@ -64,11 +64,9 @@ class list_iterator : public std::iterator < std::bidirectional_iterator_tag , typename Container::value_type - , typename std::iterator_traits::difference_type - , typename detail::add_const_if_c - ::type * - , typename detail::add_const_if_c - ::type & + , typename Container::difference_type + , typename detail::if_c::type + , typename detail::if_c::type > { protected: @@ -83,10 +81,8 @@ class list_iterator public: typedef typename Container::value_type value_type; - typedef typename detail::add_const_if_c - ::type *pointer; - typedef typename detail::add_const_if_c - ::type &reference; + typedef typename detail::if_c::type pointer; + typedef typename detail::if_c::type reference; list_iterator() : members_ (node_ptr(0), 0) @@ -133,17 +129,17 @@ class list_iterator return result; } - bool operator== (const list_iterator& i) const - { return members_.nodeptr_ == i.pointed_node(); } + friend bool operator== (const list_iterator& l, const list_iterator& r) + { return l.pointed_node() == r.pointed_node(); } - bool operator!= (const list_iterator& i) const - { return !operator== (i); } + friend bool operator!= (const list_iterator& l, const list_iterator& r) + { return !(l == r); } reference operator*() const { return *operator->(); } pointer operator->() const - { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + { return detail::boost_intrusive_get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } const Container *get_container() const { diff --git a/include/boost/intrusive/detail/slist_node.hpp b/include/boost/intrusive/detail/slist_node.hpp index a7df9e1..6ed8e4b 100644 --- a/include/boost/intrusive/detail/slist_node.hpp +++ b/include/boost/intrusive/detail/slist_node.hpp @@ -56,11 +56,9 @@ class slist_iterator : public std::iterator < std::forward_iterator_tag , typename Container::value_type - , typename std::iterator_traits::difference_type - , typename detail::add_const_if_c - ::type * - , typename detail::add_const_if_c - ::type & + , typename Container::difference_type + , typename detail::if_c::type + , typename detail::if_c::type > { protected: @@ -75,10 +73,8 @@ class slist_iterator public: typedef typename Container::value_type value_type; - typedef typename detail::add_const_if_c - ::type *pointer; - typedef typename detail::add_const_if_c - ::type &reference; + typedef typename detail::if_c::type pointer; + typedef typename detail::if_c::type reference; slist_iterator() : members_ (node_ptr(0), 0) @@ -112,17 +108,17 @@ class slist_iterator return result; } - bool operator== (const slist_iterator& i) const - { return members_.nodeptr_ == i.pointed_node(); } + friend bool operator== (const slist_iterator& l, const slist_iterator& r) + { return l.pointed_node() == r.pointed_node(); } - bool operator!= (const slist_iterator& i) const - { return !operator== (i); } + friend bool operator!= (const slist_iterator& l, const slist_iterator& r) + { return !(l == r); } reference operator*() const { return *operator->(); } pointer operator->() const - { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + { return detail::boost_intrusive_get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } const Container *get_container() const { diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 32bbfb5..1dc6b51 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -18,6 +18,7 @@ #include #include #include +//iG pending #include namespace boost { namespace intrusive { @@ -140,7 +141,8 @@ class tree_algorithms static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); + //iG pending return node_ptr(boost::const_pointer_cast(ptr)); } /// @endcond diff --git a/include/boost/intrusive/detail/tree_node.hpp b/include/boost/intrusive/detail/tree_node.hpp index 3508e85..f6a678d 100644 --- a/include/boost/intrusive/detail/tree_node.hpp +++ b/include/boost/intrusive/detail/tree_node.hpp @@ -73,11 +73,9 @@ class tree_iterator : public std::iterator < std::bidirectional_iterator_tag , typename Container::value_type - , typename std::iterator_traits::difference_type - , typename detail::add_const_if_c - ::type * - , typename detail::add_const_if_c - ::type & + , typename Container::difference_type + , typename detail::if_c::type + , typename detail::if_c::type > { protected: @@ -93,10 +91,9 @@ class tree_iterator public: typedef typename Container::value_type value_type; - typedef typename detail::add_const_if_c - ::type *pointer; - typedef typename detail::add_const_if_c - ::type &reference; + typedef typename detail::if_c::type pointer; + typedef typename detail::if_c::type reference; + tree_iterator() : members_ (0, 0) @@ -143,17 +140,17 @@ class tree_iterator return result; } - bool operator== (const tree_iterator& i) const - { return members_.nodeptr_ == i.pointed_node(); } + friend bool operator== (const tree_iterator& l, const tree_iterator& r) + { return l.pointed_node() == r.pointed_node(); } - bool operator!= (const tree_iterator& i) const - { return !operator== (i); } + friend bool operator!= (const tree_iterator& l, const tree_iterator& r) + { return !(l == r); } reference operator*() const { return *operator->(); } pointer operator->() const - { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + { return detail::boost_intrusive_get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } const Container *get_container() const { return static_cast(members_.get_ptr()); } diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index c548911..a9b876b 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -122,10 +122,10 @@ struct smart_ptr_type { return ptr;} }; -//!Overload for smart pointers to avoid ADL problems with get_pointer +//!Overload for smart pointers to avoid ADL problems with boost_intrusive_get_pointer template inline typename smart_ptr_type::pointer -get_pointer(const Ptr &ptr) +boost_intrusive_get_pointer(const Ptr &ptr) { return smart_ptr_type::get(ptr); } //This functor compares a stored value @@ -319,7 +319,7 @@ struct constptr {} const void *get_ptr() const - { return detail::get_pointer(const_void_ptr_); } + { return detail::boost_intrusive_get_pointer(const_void_ptr_); } ConstVoidPtr const_void_ptr_; }; @@ -422,13 +422,13 @@ struct member_hook_traits static pointer to_value_ptr(node_ptr n) { return detail::parent_from_member - (static_cast(detail::get_pointer(n)), P); + (static_cast(detail::boost_intrusive_get_pointer(n)), P); } static const_pointer to_value_ptr(const_node_ptr n) { return detail::parent_from_member - (static_cast(detail::get_pointer(n)), P); + (static_cast(detail::boost_intrusive_get_pointer(n)), P); } }; @@ -632,6 +632,64 @@ struct node_to_value { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } }; +//This is not standard, but should work with all compilers +union max_align +{ + char char_; + short short_; + int int_; + long long_; + #ifdef BOOST_HAS_LONG_LONG + long long long_long_; + #endif + float float_; + double double_; + long double long_double_; + void * void_ptr_; +}; + +template +class array_initializer +{ + public: + template + array_initializer(const CommonInitializer &init) + { + char *init_buf = (char*)rawbuf; + std::size_t i = 0; + try{ + for(; i != N; ++i){ + new(init_buf)T(init); + init_buf += sizeof(T); + } + } + catch(...){ + while(i--){ + init_buf -= sizeof(T); + ((T*)init_buf)->~T(); + } + throw; + } + } + + operator T* () + { return (T*)(rawbuf); } + + operator const T*() const + { return (const T*)(rawbuf); } + + ~array_initializer() + { + char *init_buf = (char*)rawbuf + N*sizeof(T); + for(std::size_t i = 0; i != N; ++i){ + init_buf -= sizeof(T); + ((T*)init_buf)->~T(); + } + } + + private: + detail::max_align rawbuf[(N*sizeof(T)-1)/sizeof(detail::max_align)+1]; +}; } //namespace detail } //namespace intrusive diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 51cc6c1..99de70d 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -886,7 +886,7 @@ class hashtable_impl } else{ size_type buckets_len = this->priv_buckets_len(); - const bucket_type *b = detail::get_pointer(this->priv_buckets()); + const bucket_type *b = detail::boost_intrusive_get_pointer(this->priv_buckets()); for (size_type n = 0; n < buckets_len; ++n, ++b){ if(!b->empty()){ return false; @@ -909,7 +909,7 @@ class hashtable_impl else{ size_type len = 0; size_type buckets_len = this->priv_buckets_len(); - const bucket_type *b = detail::get_pointer(this->priv_buckets()); + const bucket_type *b = detail::boost_intrusive_get_pointer(this->priv_buckets()); for (size_type n = 0; n < buckets_len; ++n, ++b){ len += b->size(); } @@ -1229,8 +1229,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - iterator erase(const_iterator i) - { return this->erase_and_dispose(i, detail::null_disposer()); } + void erase(const_iterator i) + { this->erase_and_dispose(i, detail::null_disposer()); } //! Effects: Erases the range pointed to by b end e. //! @@ -1241,8 +1241,8 @@ class hashtable_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return this->erase_and_dispose(b, e, detail::null_disposer()); } + void erase(const_iterator b, const_iterator e) + { this->erase_and_dispose(b, e, detail::null_disposer()); } //! Effects: Erases all the elements with the given value. //! @@ -1295,18 +1295,15 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator i, Disposer disposer + void erase_and_dispose(const_iterator i, Disposer disposer /// @cond , typename detail::enable_if_c::value >::type * = 0 /// @endcond ) { - iterator ret(i.unconst()); - ++ret; priv_erase(i, disposer, optimize_multikey_t()); this->priv_size_traits().decrement(); priv_erasure_update_cache(); - return ret; } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1322,7 +1319,7 @@ class hashtable_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) { if(b != e){ //Get the bucket number and local iterator for both iterators @@ -1347,7 +1344,6 @@ class hashtable_impl priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); priv_erasure_update_cache(first_bucket_num, last_bucket_num); } - return e.unconst(); } //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -2139,8 +2135,8 @@ class hashtable_impl } //! Effects: 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 + //! the container that is bigger or equal than n. This suggestion can be + //! used to create bucket arrays with a size that will usually improve //! container's performance. If such value does not exist, the //! higher possible value is returned. //! @@ -2153,15 +2149,15 @@ class hashtable_impl const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; size_type const* bound = std::lower_bound(primes, primes_end, n); if(bound == primes_end) - bound--; + --bound; return size_type(*bound); } //! Effects: Returns the nearest new bucket count optimized for - //! the container that is smaller than n. This suggestion can be used - //! to create bucket arrays with a size that will usually improve + //! the container that is smaller or equal than n. This suggestion can be + //! used to create bucket arrays with a size that will usually improve //! container's performance. If such value does not exist, the - //! lower possible value is returned. + //! lowest possible value is returned. //! //! Complexity: Amortized constant time. //! @@ -2171,8 +2167,8 @@ class hashtable_impl const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0]; const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; size_type const* bound = std::upper_bound(primes, primes_end, n); - if(bound != primes_end) - bound--; + if(bound != primes) + --bound; return size_type(*bound); } @@ -2240,7 +2236,7 @@ class hashtable_impl { return this->priv_real_bucket_traits().bucket_count(); } static node_ptr uncast(const_node_ptr ptr) - { return node_ptr(const_cast(detail::get_pointer(ptr))); } + { return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } node &priv_value_to_node(value_type &v) { return *this->get_real_value_traits().to_node_ptr(v); } diff --git a/include/boost/intrusive/list.hpp b/include/boost/intrusive/list.hpp index 965baa7..ee3e5ba 100644 --- a/include/boost/intrusive/list.hpp +++ b/include/boost/intrusive/list.hpp @@ -30,6 +30,7 @@ #include #include #include +//iG pending #include namespace boost { namespace intrusive { @@ -129,8 +130,8 @@ class list_impl //Const cast emulation for smart pointers static node_ptr uncast(const_node_ptr ptr) { - //return node_ptr(detail::get_pointer(ptr))); - return const_cast(detail::get_pointer(ptr)); + return const_cast(detail::boost_intrusive_get_pointer(ptr)); + //iG pending return node_ptr(boost::const_pointer_cast(ptr)); } node_ptr get_root_node() @@ -172,6 +173,22 @@ class list_impl real_value_traits &get_real_value_traits(detail::bool_) { return data_.get_value_traits(*this); } + const value_traits &get_value_traits() const + { return data_; } + + value_traits &get_value_traits() + { return data_; } + + protected: + node &prot_root_node() + { return data_.root_plus_size_.root_; } + + node const &prot_root_node() const + { return data_.root_plus_size_.root_; } + + void prot_set_size(size_type s) + { data_.root_plus_size_.set_size(s); } + /// @endcond public: @@ -971,8 +988,8 @@ class list_impl { if(node_traits::get_next(this->get_root_node()) != node_traits::get_previous(this->get_root_node())){ - list_impl carry; - list_impl counter[64]; + list_impl carry(this->get_value_traits()); + detail::array_initializer counter(this->get_value_traits()); int fill = 0; while(!this->empty()){ carry.splice(carry.cbegin(), *this, this->cbegin()); @@ -1268,7 +1285,7 @@ class list_impl static list_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { root_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &root_plus_size::root_); data_t *d = detail::parent_from_member ( r, &data_t::root_plus_size_); list_impl *s = detail::parent_from_member(d, &list_impl::data_); diff --git a/include/boost/intrusive/member_value_traits.hpp b/include/boost/intrusive/member_value_traits.hpp index ce7e56b..4490d49 100644 --- a/include/boost/intrusive/member_value_traits.hpp +++ b/include/boost/intrusive/member_value_traits.hpp @@ -49,13 +49,13 @@ struct member_value_traits static pointer to_value_ptr(node_ptr n) { return pointer(detail::parent_from_member - (detail::get_pointer(n), PtrToMember)); + (detail::boost_intrusive_get_pointer(n), PtrToMember)); } static const_pointer to_value_ptr(const_node_ptr n) { return pointer(detail::parent_from_member - (detail::get_pointer(n), PtrToMember)); + (detail::boost_intrusive_get_pointer(n), PtrToMember)); } }; diff --git a/include/boost/intrusive/rbtree.hpp b/include/boost/intrusive/rbtree.hpp index 8d9cacf..c8e8ab5 100644 --- a/include/boost/intrusive/rbtree.hpp +++ b/include/boost/intrusive/rbtree.hpp @@ -33,6 +33,7 @@ #include #include #include +//iG pending #include namespace boost { namespace intrusive { @@ -110,10 +111,8 @@ class rbtree_impl typedef std::reverse_iterator const_reverse_iterator; typedef typename real_value_traits::node_traits node_traits; typedef typename node_traits::node node; - typedef typename boost::pointer_to_other - ::type node_ptr; - typedef typename boost::pointer_to_other - ::type const_node_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; typedef rbtree_algorithms node_algorithms; static const bool constant_time_size = Config::constant_time_size; @@ -152,7 +151,7 @@ class rbtree_impl {} node_plus_pred_t node_plus_pred_; } data_; - + const value_compare &priv_comp() const { return data_.node_plus_pred_.get(); } @@ -167,7 +166,8 @@ class rbtree_impl static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(detail::get_pointer(ptr))); + return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); +//iG pending return node_ptr(boost::const_pointer_cast(ptr)); } size_traits &priv_size_traits() @@ -188,6 +188,19 @@ class rbtree_impl real_value_traits &get_real_value_traits(detail::bool_) { return data_.get_value_traits(*this); } + protected: + value_compare &prot_comp() + { return priv_comp(); } + + const node &prot_header_node() const + { return priv_header(); } + + node &prot_header_node() + { return priv_header(); } + + void prot_set_size(size_type s) + { this->priv_size_traits().set_size(s); } + /// @endcond public: @@ -1390,7 +1403,7 @@ class rbtree_impl static rbtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { header_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); node_plus_pred_t *n = detail::parent_from_member (r, &node_plus_pred_t::header_plus_size_); data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index ca6f7eb..89abcd6 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -157,7 +157,7 @@ class rbtree_algorithms static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); } /// @endcond diff --git a/include/boost/intrusive/set.hpp b/include/boost/intrusive/set.hpp index 54c5a65..c85ab08 100644 --- a/include/boost/intrusive/set.hpp +++ b/include/boost/intrusive/set.hpp @@ -75,9 +75,19 @@ class set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + //static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + /// @cond private: tree_type tree_; + + protected: + node &prot_header_node(){ return tree_.prot_header_node(); } + node const &prot_header_node() const{ return tree_.prot_header_node(); } + void prot_set_size(size_type s){ tree_.prot_set_size(s); } + value_compare &prot_comp(){ return tree_.prot_comp(); } + /// @endcond public: @@ -1265,9 +1275,18 @@ class multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + //static const bool stateful_value_traits = detail::is_stateful_value_traits::value; + /// @cond private: tree_type tree_; + + protected: + node &prot_header_node(){ return tree_.prot_header_node(); } + node const &prot_header_node() const{ return tree_.prot_header_node(); } + void prot_set_size(size_type s){ tree_.prot_set_size(s); } + value_compare &prot_comp(){ return tree_.prot_comp(); } /// @endcond public: @@ -1450,7 +1469,7 @@ class multiset_impl //! //! Throws: Nothing. //! - //! Complexity: Constant. + //! Complexity: Logarithmic. static multiset_impl &container_from_iterator(iterator it) { return *detail::parent_from_member @@ -1464,7 +1483,7 @@ class multiset_impl //! //! Throws: Nothing. //! - //! Complexity: Constant. + //! Complexity: Logarithmic. static const multiset_impl &container_from_iterator(const_iterator it) { return *detail::parent_from_member diff --git a/include/boost/intrusive/sgtree.hpp b/include/boost/intrusive/sgtree.hpp index 5507893..5cc361a 100644 --- a/include/boost/intrusive/sgtree.hpp +++ b/include/boost/intrusive/sgtree.hpp @@ -310,7 +310,7 @@ class sgtree_impl { return data_.node_plus_pred_.header_plus_alpha_.header_; } static node_ptr uncast(const_node_ptr ptr) - { return node_ptr(const_cast(detail::get_pointer(ptr))); } + { return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } size_traits &priv_size_traits() { return data_.node_plus_pred_.size_traits_; } @@ -1631,7 +1631,7 @@ class sgtree_impl static sgtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { header_plus_alpha *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_alpha::header_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &header_plus_alpha::header_); node_plus_pred_t *n = detail::parent_from_member (r, &node_plus_pred_t::header_plus_alpha_); data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); diff --git a/include/boost/intrusive/sgtree_algorithms.hpp b/include/boost/intrusive/sgtree_algorithms.hpp index bb6ef06..99e9d39 100644 --- a/include/boost/intrusive/sgtree_algorithms.hpp +++ b/include/boost/intrusive/sgtree_algorithms.hpp @@ -70,7 +70,7 @@ class sgtree_algorithms static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); } /// @endcond diff --git a/include/boost/intrusive/slist.hpp b/include/boost/intrusive/slist.hpp index 8314a75..6aad69e 100644 --- a/include/boost/intrusive/slist.hpp +++ b/include/boost/intrusive/slist.hpp @@ -31,6 +31,7 @@ #include #include //std::size_t #include //std::pair +//iG pending #include namespace boost { namespace intrusive { @@ -129,10 +130,9 @@ class slist_impl typedef slist_iterator const_iterator; typedef typename real_value_traits::node_traits node_traits; typedef typename node_traits::node node; - typedef typename boost::pointer_to_other - ::type node_ptr; - typedef typename boost::pointer_to_other - ::type const_node_ptr; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename detail::if_c < Config::linear , linear_slist_algorithms @@ -206,7 +206,8 @@ class slist_impl { data_.root_plus_size_.last_ = n; } static node_ptr uncast(const_node_ptr ptr) - { return node_ptr(const_cast(detail::get_pointer(ptr))); } + { return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } +//iG pending { return boost::const_pointer_cast(ptr); } void set_default_constructed_state() { @@ -251,6 +252,22 @@ class slist_impl real_value_traits &get_real_value_traits(detail::bool_) { return data_.get_value_traits(*this); } + const value_traits &get_value_traits() const + { return data_; } + + value_traits &get_value_traits() + { return data_; } + + protected: + node &prot_root_node() + { return data_.root_plus_size_.root_; } + + node const &prot_root_node() const + { return data_.root_plus_size_.root_; } + + void prot_set_size(size_type s) + { data_.root_plus_size_.set_size(s); } + /// @endcond public: @@ -1220,7 +1237,7 @@ class slist_impl //! assigned to the last spliced element or prev if x is empty. //! This iterator can be used as new "prev" iterator for a new splice_after call. //! that will splice new values after the previously spliced values. - void splice(const_iterator it, slist_impl &x, iterator *last = 0) + void splice(const_iterator it, slist_impl &x, const_iterator *last = 0) { this->splice_after(this->previous(it), x, last); } //! Requires: it p must be a valid iterator of *this. @@ -1295,8 +1312,9 @@ class slist_impl { if (node_traits::get_next(node_traits::get_next(this->get_root_node())) != this->get_root_node()) { - slist_impl carry; - slist_impl counter[64]; + + slist_impl carry(this->get_value_traits()); + detail::array_initializer counter(this->get_value_traits()); int fill = 0; const_iterator last_inserted; while(!this->empty()){ @@ -1879,7 +1897,7 @@ class slist_impl //singly linked lists (because "end" is represented by the null pointer) BOOST_STATIC_ASSERT(!linear); root_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), (&root_plus_size::root_)); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), (&root_plus_size::root_)); data_t *d = detail::parent_from_member ( r, &data_t::root_plus_size_); slist_impl *s = detail::parent_from_member(d, &slist_impl::data_); diff --git a/include/boost/intrusive/splay_set.hpp b/include/boost/intrusive/splay_set.hpp index 9727d14..f899e78 100644 --- a/include/boost/intrusive/splay_set.hpp +++ b/include/boost/intrusive/splay_set.hpp @@ -74,6 +74,8 @@ class splay_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; @@ -1286,6 +1288,8 @@ class splay_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; diff --git a/include/boost/intrusive/splaytree.hpp b/include/boost/intrusive/splaytree.hpp index 4020c85..1cb2a2a 100644 --- a/include/boost/intrusive/splaytree.hpp +++ b/include/boost/intrusive/splaytree.hpp @@ -166,7 +166,7 @@ class splaytree_impl static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(detail::get_pointer(ptr))); + return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } size_traits &priv_size_traits() @@ -1405,7 +1405,7 @@ class splaytree_impl static splaytree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { header_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); node_plus_pred_t *n = detail::parent_from_member (r, &node_plus_pred_t::header_plus_size_); data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); diff --git a/include/boost/intrusive/splaytree_algorithms.hpp b/include/boost/intrusive/splaytree_algorithms.hpp index eb25e9f..777b3b9 100644 --- a/include/boost/intrusive/splaytree_algorithms.hpp +++ b/include/boost/intrusive/splaytree_algorithms.hpp @@ -147,7 +147,7 @@ class splaytree_algorithms private: static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); } /// @endcond diff --git a/include/boost/intrusive/treap.hpp b/include/boost/intrusive/treap.hpp index b7c9ed2..86bdd01 100644 --- a/include/boost/intrusive/treap.hpp +++ b/include/boost/intrusive/treap.hpp @@ -116,7 +116,7 @@ class treap_impl ::type node_ptr; typedef typename boost::pointer_to_other ::type const_node_ptr; - typedef treap_algorithms node_algorithms; + typedef treap_algorithms node_algorithms; static const bool constant_time_size = Config::constant_time_size; static const bool stateful_value_traits = detail::is_stateful_value_traits::value; @@ -184,7 +184,7 @@ class treap_impl static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(detail::get_pointer(ptr))); + return node_ptr(const_cast(detail::boost_intrusive_get_pointer(ptr))); } size_traits &priv_size_traits() @@ -1482,7 +1482,7 @@ class treap_impl static treap_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) { header_plus_size *r = detail::parent_from_member - ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + ( detail::boost_intrusive_get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); typename node_plus_pred_t::header_plus_priority_size *n = detail::parent_from_member < typename node_plus_pred_t::header_plus_priority_size diff --git a/include/boost/intrusive/treap_algorithms.hpp b/include/boost/intrusive/treap_algorithms.hpp index 6c05efa..a120815 100644 --- a/include/boost/intrusive/treap_algorithms.hpp +++ b/include/boost/intrusive/treap_algorithms.hpp @@ -145,7 +145,7 @@ class treap_algorithms static node_ptr uncast(const_node_ptr ptr) { - return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + return node_ptr(const_cast(::boost::intrusive::detail::boost_intrusive_get_pointer(ptr))); } /// @endcond diff --git a/include/boost/intrusive/treap_set.hpp b/include/boost/intrusive/treap_set.hpp index 12611ee..ef38a1e 100644 --- a/include/boost/intrusive/treap_set.hpp +++ b/include/boost/intrusive/treap_set.hpp @@ -75,6 +75,8 @@ class treap_set_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; @@ -1382,6 +1384,8 @@ class treap_multiset_impl typedef typename implementation_defined::const_node_ptr const_node_ptr; typedef typename implementation_defined::node_algorithms node_algorithms; + static const bool constant_time_size = Config::constant_time_size; + /// @cond private: tree_type tree_; diff --git a/include/boost/intrusive/unordered_set.hpp b/include/boost/intrusive/unordered_set.hpp index 47d1aab..2b40f61 100644 --- a/include/boost/intrusive/unordered_set.hpp +++ b/include/boost/intrusive/unordered_set.hpp @@ -248,7 +248,7 @@ class unordered_set_impl //! Effects: Returns the number of elements stored in the unordered_set. //! //! Complexity: Linear to elements contained in *this if - //! constant-time size option is enabled. Constant-time otherwise. + //! constant-time size option is disabled. Constant-time otherwise. //! //! Throws: Nothing. size_type size() const @@ -395,8 +395,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - iterator erase(const_iterator i) - { return table_.erase(i); } + void erase(const_iterator i) + { table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -407,8 +407,8 @@ class unordered_set_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return table_.erase(b, e); } + void erase(const_iterator b, const_iterator e) + { table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -460,12 +460,12 @@ class unordered_set_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator i, Disposer disposer + void erase_and_dispose(const_iterator i, Disposer disposer /// @cond , typename detail::enable_if_c::value >::type * = 0 /// @endcond ) - { return table_.erase_and_dispose(i, disposer); } + { table_.erase_and_dispose(i, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -480,8 +480,8 @@ class unordered_set_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return table_.erase_and_dispose(b, e, disposer); } + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { table_.erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! @@ -1305,7 +1305,7 @@ class unordered_multiset_impl //! Effects: Returns the number of elements stored in the unordered_multiset. //! //! Complexity: Linear to elements contained in *this if - //! constant-time size option is enabled. Constant-time otherwise. + //! constant-time size option is disabled. Constant-time otherwise. //! //! Throws: Nothing. size_type size() const @@ -1387,8 +1387,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased element. No destructors are called. - iterator erase(const_iterator i) - { return table_.erase(i); } + void erase(const_iterator i) + { table_.erase(i); } //! Effects: Erases the range pointed to by b end e. //! @@ -1399,8 +1399,8 @@ class unordered_multiset_impl //! //! Note: Invalidates the iterators (but not the references) //! to the erased elements. No destructors are called. - iterator erase(const_iterator b, const_iterator e) - { return table_.erase(b, e); } + void erase(const_iterator b, const_iterator e) + { table_.erase(b, e); } //! Effects: Erases all the elements with the given value. //! @@ -1453,17 +1453,17 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator i, Disposer disposer + void erase_and_dispose(const_iterator i, Disposer disposer /// @cond , typename detail::enable_if_c::value >::type * = 0 /// @endcond ) - { return table_.erase_and_dispose(i, disposer); } + { table_.erase_and_dispose(i, disposer); } #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) template - iterator erase_and_dispose(const_iterator i, Disposer disposer) - { return this->erase_and_dispose(const_iterator(i), disposer); } + void erase_and_dispose(const_iterator i, Disposer disposer) + { this->erase_and_dispose(const_iterator(i), disposer); } #endif //! Requires: Disposer::operator()(pointer) shouldn't throw. @@ -1479,8 +1479,8 @@ class unordered_multiset_impl //! Note: Invalidates the iterators //! to the erased elements. template - iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) - { return table_.erase_and_dispose(b, e, disposer); } + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { table_.erase_and_dispose(b, e, disposer); } //! Requires: Disposer::operator()(pointer) shouldn't throw. //! From d031cebdb6ac4558bee1085e61e1e4039c66db20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 12 Mar 2010 13:22:13 +0000 Subject: [PATCH 23/29] Interprocess: [@https://svn.boost.org/trac/boost/ticket/3439 #3439], [@https://svn.boost.org/trac/boost/ticket/3846 #3846], [@https://svn.boost.org/trac/boost/ticket/3947 #3947], [@https://svn.boost.org/trac/boost/ticket/3985 #3985]. Intrusive: [@https://svn.boost.org/trac/boost/ticket/3668 #3668], [@https://svn.boost.org/trac/boost/ticket/3339 #3688], [@https://svn.boost.org/trac/boost/ticket/3698 #3698], [@https://svn.boost.org/trac/boost/ticket/3706 #3706], [@https://svn.boost.org/trac/boost/ticket/3721 #3721]. [@https://svn.boost.org/trac/boost/ticket/3729 #3729], [@https://svn.boost.org/trac/boost/ticket/3746 #3746], [@https://svn.boost.org/trac/boost/ticket/3781 #3781], [@https://svn.boost.org/trac/boost/ticket/3829 #3829], [@https://svn.boost.org/trac/boost/ticket/3840 #3840], [@https://svn.boost.org/trac/boost/ticket/3339 #3339], [@https://svn.boost.org/trac/boost/ticket/3419 #3419], [@https://svn.boost.org/trac/boost/ticket/3431 #3431], [SVN r60515] --- test/common_functors.hpp | 2 +- test/set_test.cpp | 1 + test/smart_ptr.hpp | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/common_functors.hpp b/test/common_functors.hpp index ebfc846..7f7c675 100644 --- a/test/common_functors.hpp +++ b/test/common_functors.hpp @@ -29,7 +29,7 @@ class delete_disposer { typedef typename std::iterator_traits::value_type value_type; BOOST_INTRUSIVE_INVARIANT_ASSERT(( detail::is_same::value )); - delete detail::get_pointer(p); + delete detail::boost_intrusive_get_pointer(p); } }; diff --git a/test/set_test.cpp b/test/set_test.cpp index aa1ca2b..97210d8 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -147,6 +147,7 @@ class test_main_template } }; + int main( int, char* [] ) { test_main_template()(); diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index 24ac8bb..c5ccfc5 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -303,10 +303,10 @@ inline void swap (smart_ptr &pt, pt2 = ptr; } -//!detail::get_pointer() enables boost::mem_fn to recognize smart_ptr. +//!detail::boost_intrusive_get_pointer() enables boost::mem_fn to recognize smart_ptr. //!Never throws. template -inline T* get_pointer(const smart_ptr & p) +inline T* boost_intrusive_get_pointer(const smart_ptr & p) { return p.get(); } //!Simulation of static_cast between pointers. Never throws. From 1bbbf0862f2c4f42b7e9a89d1470f3ed7e525c4f Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Tue, 16 Mar 2010 21:00:27 +0000 Subject: [PATCH 24/29] Quality size_t with std::. Fixes #4021 [SVN r60656] --- include/boost/intrusive/detail/tree_algorithms.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive/detail/tree_algorithms.hpp b/include/boost/intrusive/detail/tree_algorithms.hpp index 1dc6b51..9ad2b4e 100644 --- a/include/boost/intrusive/detail/tree_algorithms.hpp +++ b/include/boost/intrusive/detail/tree_algorithms.hpp @@ -1501,7 +1501,7 @@ class tree_algorithms static node_ptr vine_to_subtree(node_ptr old_root, std::size_t count) { - std::size_t leaf_nodes = count + 1 - ((size_t) 1 << floor_log2 (count + 1)); + std::size_t leaf_nodes = count + 1 - ((std::size_t) 1 << floor_log2 (count + 1)); std::size_t vine_nodes = count - leaf_nodes; node_ptr new_root = compress_subtree(old_root, leaf_nodes); From 7290a9a8b348d20b21a890a215c5ca545fa8e274 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 20 Apr 2010 17:54:16 +0000 Subject: [PATCH 25/29] Fixed tab and no-newline-at-end-of-file issues from inspection report [SVN r61435] --- test/generic_assoc_test.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 50931c0..5d10d72 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -402,9 +402,9 @@ void test_generic_assoc::test_insert_before for(vec_iterator it(--values.end()); true; --it){ testset.push_front(*it); - if(it == values.begin()){ + if(it == values.begin()){ break; - } + } } BOOST_TEST(testset.size() == values.size()); TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); From ba311e69cfb75ca0c24ce859992e13be9abf3a54 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 29 Apr 2010 00:35:20 +0000 Subject: [PATCH 26/29] Mutable references are ill-formed. Remove a sporadic "mutable". [SVN r61664] --- include/boost/intrusive/detail/transform_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/intrusive/detail/transform_iterator.hpp b/include/boost/intrusive/detail/transform_iterator.hpp index a9de49e..15ef3ab 100644 --- a/include/boost/intrusive/detail/transform_iterator.hpp +++ b/include/boost/intrusive/detail/transform_iterator.hpp @@ -46,7 +46,7 @@ struct operator_arrow_proxy // This function is needed for MWCW and BCC, which won't call operator-> // again automatically per 13.3.1.2 para 8 // operator T*() const { return &m_value; } - mutable T &m_value; + T &m_value; }; template From 94a5c533f90d3e8d7502f9209631101e7e2f51be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 24 Aug 2010 17:13:19 +0000 Subject: [PATCH 27/29] More changes for Boost 1.45 [SVN r64984] --- doc/intrusive.qbk | 170 ++++++++++++++---- example/doc_function_hooks.cpp | 76 ++++++++ example/doc_recursive.cpp | 53 ++++++ example/doc_recursive_member.cpp | 86 +++++++++ proj/vc7ide/Intrusive.sln | 18 +- .../vc7ide/_intrusivelib/_intrusivelib.vcproj | 12 ++ proj/vc7ide/any_test/any_test.vcproj | 2 +- proj/vc7ide/avl_multiset/avl_multiset.vcproj | 2 +- proj/vc7ide/avl_set/avl_set.vcproj | 2 +- .../custom_bucket_traits.vcproj | 2 +- proj/vc7ide/default_hook/default_hook.vcproj | 2 +- .../external_value_traits.vcproj | 2 +- .../vc7ide/function_hook/function_hook.vcproj | 133 ++++++++++++++ proj/vc7ide/list/list.vcproj | 2 +- .../make_functions/make_functions.vcproj | 2 +- proj/vc7ide/multiset/multiset.vcproj | 2 +- proj/vc7ide/recursive/recursive.vcproj | 133 ++++++++++++++ proj/vc7ide/set/set.vcproj | 2 +- proj/vc7ide/sg_multiset/sg_multiset.vcproj | 2 +- proj/vc7ide/sg_set/sg_set.vcproj | 2 +- proj/vc7ide/slist/slist.vcproj | 2 +- .../splay_multiset/splay_multiset.vcproj | 2 +- proj/vc7ide/splay_set/splay_set.vcproj | 2 +- .../stateful_value_traits.vcproj | 2 +- proj/vc7ide/to-do.txt | 1 + .../treap_multiset/treap_multiset.vcproj | 2 +- proj/vc7ide/treap_set/treap_set.vcproj | 2 +- .../unordered_multiset.vcproj | 2 +- .../vc7ide/unordered_set/unordered_set.vcproj | 2 +- proj/vc7ide/virtual_base/virtual_base.vcproj | 2 +- test/function_hook_test.cpp | 152 ++++++++++++++++ test/generic_assoc_test.hpp | 4 +- test/list_test.cpp | 3 - test/recursive_test.cpp | 71 ++++++++ test/smart_ptr.hpp | 3 +- 35 files changed, 893 insertions(+), 64 deletions(-) create mode 100644 example/doc_function_hooks.cpp create mode 100644 example/doc_recursive.cpp create mode 100644 example/doc_recursive_member.cpp create mode 100644 proj/vc7ide/function_hook/function_hook.vcproj create mode 100644 proj/vc7ide/recursive/recursive.vcproj create mode 100644 test/function_hook_test.cpp create mode 100644 test/recursive_test.cpp diff --git a/doc/intrusive.qbk b/doc/intrusive.qbk index 4c14d1c..f459c5f 100644 --- a/doc/intrusive.qbk +++ b/doc/intrusive.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2007-2009 Ion Gaztanaga + / Copyright (c) 2007-2010 Ion Gaztanaga / / Distributed under the Boost Software License, Version 1.0. (See accompanying / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,7 +8,7 @@ [library Boost.Intrusive [quickbook 1.4] [authors [Krzikalla, Olaf], [Gaztanaga, Ion]] - [copyright 2005 Olaf Krzikalla, 2006-2009 Ion Gaztanaga] + [copyright 2005 Olaf Krzikalla, 2006-2010 Ion Gaztanaga] [id intrusive] [dirname intrusive] [purpose Intrusive containers] @@ -198,7 +198,7 @@ Intrusive containers have also downsides: swapping can be used to implement move capabilities. To ease the implementation of copy constructors and assignment operators of classes storing [*Boost.Intrusive] containers, [*Boost.Intrusive] offers special cloning functions. See - [link intrusive.clone_from Cloning [*Boost.Intrusive] containers] section for more information. + [link intrusive.clone_from Cloning Boost.Intrusive containers] section for more information. * Analyzing the thread safety of a program that uses containers is harder with intrusive containers, because the container might be modified indirectly without an explicit call to a container member. @@ -246,7 +246,10 @@ just include: Every class to be inserted in an intrusive container, needs to contain a hook that will offer the necessary data and resources to be insertable in the container. With [*Boost.Intrusive] you just choose the hook to be a public base class or -a public member of the class to be inserted. +a public member of the class to be inserted. [*Boost.Intrusive] also offers +more flexible hooks for advanced users, as explained in the chapter +[link intrusive.function_hooks Using function hooks], but usually base or member +hooks are good enough for most users. [section:usage_base_hook Using base hooks] @@ -451,6 +454,7 @@ stored object is not bound to or managed by the container: [endsect] + [endsect] [section:usage_when When to use?] @@ -2147,7 +2151,7 @@ that erase an element from the container. [endsect] -[section:clone_from Cloning [*Boost.Intrusive] containers] +[section:clone_from Cloning Boost.Intrusive containers] As previously mentioned, [*Boost.Intrusive] containers are [*non-copyable and non-assignable], because intrusive containers don't allocate memory at all. To implement a copy-constructor or assignment operator, @@ -2190,6 +2194,105 @@ Here is an example of `clone_from`: [endsect] +[section:function_hooks Using function hooks] + +A programmer might find that base or member hooks are not flexible enough in some situations. +In some applications it would be optimal to put a hook deep inside a member of a class or just outside the class. +[*Boost.Intrusive] has an easy option to allow such cases: [classref boost::intrusive::function_hook function_hook]. + +This option is similar to [classref boost::intrusive::member_hook member_hook] or +[classref boost::intrusive::base_hook base_hook], but the programmer can specify a function +object that tells the container how to obtain a hook from a value and vice versa. +The programmer just needs to define the following function object: + +[c++] + + //This functor converts between value_type and a hook_type + struct Functor + { + //Required types + typedef /*impl-defined*/ hook_type; + typedef /*impl-defined*/ hook_ptr; + typedef /*impl-defined*/ const_hook_ptr; + typedef /*impl-defined*/ value_type; + typedef /*impl-defined*/ pointer; + typedef /*impl-defined*/ const_pointer; + //Required static functions + static hook_ptr to_hook_ptr (value_type &value); + static const_hook_ptr to_hook_ptr(const value_type &value); + static pointer to_value_ptr(hook_ptr n); + static const_pointer to_value_ptr(const_hook_ptr n); + }; + +Converting from values to hooks is generally easy, since most hooks are +in practice members or base classes of class data members. The inverse operation +is a bit more complicated, but [*Boost.Intrusive] offers a bit of help with the function +[funcref boost::intrusive::get_parent_from_member get_parent_from_member], +which allows easy conversions from the address of a data member to the address of +the parent holding that member. Let's see a little example of +[classref boost::intrusive::function_hook function_hook]: + +[import ../example/doc_function_hooks.cpp] +[doc_function_hooks] + +[endsect] + + +[section:recursive Recursive Boost.Intrusive containers] + +[*Boost.Intrusive] containers can be used to define recursive structures very easily, +allowing complex data structures with very low overhead. Let's see an example: + +[import ../example/doc_recursive.cpp] +[doc_recursive] + +Recursive data structures using [*Boost.Intrusive] containers must avoid using hook deduction to avoid early type +instantiation: + +[c++] + + //This leads to compilation error (Recursive is instantiated by + //'list' to deduce hook properties (pointer type, tag, safe-mode...) + class Recursive + { //... + + list< Recursive > l; + //... + }; + + //Ok, programmer must specify the hook type to avoid early Recursive instantiation + class Recursive + { //... + list< Recursive, base_hook > l; + //... + }; + + +Member hooks are not suitable for recursive structures: + +[c++] + + class Recursive + { + private: + Recursive(const Recursive&); + Recursive & operator=(const Recursive&); + + public: + list_member_hook<> memhook; + list< Recursive, member_hook, &Recursive::memhook> > children; + }; + +Specifying `&Recursive::memhook` (that is, the offset between memhook and Recursive) provokes an early +instantiation of `Recursive`. To define recursive structures using member hooks, a programmer should use +[classref ::boost::interprocess::function_hook function_hook]: + +[import ../example/doc_recursive_member.cpp] +[doc_recursive_member] + +[endsect] + + [section:using_smart_pointers Using smart pointers with Boost.Intrusive containers] [*Boost.Intrusive] hooks can be configured to use other pointers than raw pointers. @@ -3313,7 +3416,7 @@ If you are concerned with file sizes and compilation times, this option is your When designing [*Boost.Intrusive] the following guidelines have been taken into account: -[section: Boost.Intrusive in performance sensitive environments] +[section:performance_sensitive Boost.Intrusive in performance sensitive environments] [*Boost.Intrusive] should be a valuable tool in performance sensitive environments, and following this guideline, [*Boost.Intrusive] has been designed to offer well @@ -3327,7 +3430,7 @@ constructions. [endsect] -[section: Boost.Intrusive in space constrained environments] +[section:space_constrained Boost.Intrusive in space constrained environments] [*Boost.Intrusive] should be useful in space constrained environments, and following this guideline [*Boost.Intrusive] separates node algorithms @@ -3344,7 +3447,7 @@ when the container is empty or contains few values. [endsect] -[section: Boost.Intrusive as a basic building block] +[section:basic_building_block Boost.Intrusive as a basic building block] [*Boost.Intrusive] can be a basic building block to build more complex containers and this potential has motivated many design decisions. For example, the ability @@ -3358,7 +3461,7 @@ functions come in handy when implementing non-intrusive containers [endsect] -[section: Extending Boost.Intrusive] +[section:extending_intrusive Extending Boost.Intrusive] [*Boost.Intrusive] offers a wide range of containers but also allows the construction of custom containers reusing [*Boost.Intrusive] elements. @@ -3728,6 +3831,28 @@ all the objects to be inserted in intrusive containers in containers like `std:: [section:release_notes Release Notes] +[section:release_notes_boost_1_45_00 Boost 1.45 Release] + +* Added `function_hook` option. +* Fixed bugs + [@https://svn.boost.org/trac/boost/ticket/3668 #3668], + [@https://svn.boost.org/trac/boost/ticket/3339 #3688], + [@https://svn.boost.org/trac/boost/ticket/3698 #3698], + [@https://svn.boost.org/trac/boost/ticket/3706 #3706], + [@https://svn.boost.org/trac/boost/ticket/3721 #3721]. + [@https://svn.boost.org/trac/boost/ticket/3729 #3729], + [@https://svn.boost.org/trac/boost/ticket/3746 #3746], + [@https://svn.boost.org/trac/boost/ticket/3781 #3781], + [@https://svn.boost.org/trac/boost/ticket/3829 #3829], + [@https://svn.boost.org/trac/boost/ticket/3840 #3840], + [@https://svn.boost.org/trac/boost/ticket/3339 #3339], + [@https://svn.boost.org/trac/boost/ticket/3419 #3419], + [@https://svn.boost.org/trac/boost/ticket/3431 #3431], + [@https://svn.boost.org/trac/boost/ticket/4021 #4021], + +[endsect] + + [section:release_notes_boost_1_40_00 Boost 1.40 Release] * Code cleanup in tree_algorithms.hpp and avl_tree_algorithms.hpp @@ -3849,29 +3974,4 @@ helpful discussions. [endsect] -[xinclude autodoc.xml] - -[section:license_notices License notices] - -Most of the internal implementation of red-black trees is based on that of SGI STL stl_tree.h file: - -['Copyright (c) 1996,1997 Silicon Graphics Computer Systems, Inc. -Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Silicon Graphics makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.] - -['Copyright (c) 1994 Hewlett-Packard Company -Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.] - -The tree destruction algorithm is based on Julienne Walker and The EC Team code: - -['This code is in the public domain. Anyone may -use it or change it in any way that they see -fit. The author assumes no responsibility for -damages incurred through use of the original -code or any variations thereof.] - -['It is requested, but not required, that due -credit is given to the original author and -anyone who has modified the code through -a header comment, such as this one.] - -[endsect] +[xinclude autodoc.xml] \ No newline at end of file diff --git a/example/doc_function_hooks.cpp b/example/doc_function_hooks.cpp new file mode 100644 index 0000000..f7b6a87 --- /dev/null +++ b/example/doc_function_hooks.cpp @@ -0,0 +1,76 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2010 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +//[doc_function_hooks +#include +#include + +using namespace boost::intrusive; + +struct MyClass +{ + int dummy; + //This internal type has a member hook + struct InnerNode + { + int dummy; + list_member_hook<> hook; + } inner; +}; + +//This functor converts between MyClass and InnerNode's member hook +struct Functor +{ + //Required types + typedef list_member_hook<> hook_type; + typedef hook_type* hook_ptr; + typedef const hook_type* const_hook_ptr; + typedef MyClass value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + //Required static functions + static hook_ptr to_hook_ptr (value_type &value) + { return &value.inner.hook; } + static const_hook_ptr to_hook_ptr(const value_type &value) + { return &value.inner.hook; } + static pointer to_value_ptr(hook_ptr n) + { + return get_parent_from_member + (get_parent_from_member(n, &MyClass::InnerNode::hook) + ,&MyClass::inner + ); + } + static const_pointer to_value_ptr(const_hook_ptr n) + { + return get_parent_from_member + (get_parent_from_member(n, &MyClass::InnerNode::hook) + ,&MyClass::inner + ); + } +}; + +//Define a list that will use the hook accessed through the function object +typedef list< MyClass, function_hook< Functor> > List; + +int main() +{ + MyClass n; + List l; + //Insert the node in both lists + l.insert(l.begin(), n); + assert(l.size() == 1); + return 0; +} +//] + +#include diff --git a/example/doc_recursive.cpp b/example/doc_recursive.cpp new file mode 100644 index 0000000..c161e14 --- /dev/null +++ b/example/doc_recursive.cpp @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2009 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +//[doc_recursive +#include +#include + +using namespace boost::intrusive; + +typedef list_base_hook<> BaseHook; + +//A recursive class +class Recursive : public BaseHook +{ + private: + Recursive(const Recursive&); + Recursive & operator=(const Recursive&); + + public: + Recursive() : BaseHook(), children(){} + list< Recursive, base_hook > children; +}; + +int main() +{ + Recursive f, f2; + //A recursive list of Recursive + list< Recursive, base_hook > l; + + //Insert a node in parent list + l.insert(l.begin(), f); + + //Insert a node in child list + l.begin()->children.insert(l.begin()->children.begin(), f2); + + //Objects properly inserted + assert(l.size() == l.begin()->children.size()); + assert(l.size() == 1); + + //Clear both lists + l.begin()->children.clear(); + l.clear(); + return 0; +} +//] diff --git a/example/doc_recursive_member.cpp b/example/doc_recursive_member.cpp new file mode 100644 index 0000000..042acbe --- /dev/null +++ b/example/doc_recursive_member.cpp @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2010 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +//[doc_recursive_member +#include +#include + +using namespace boost::intrusive; + +class Recursive; + +//Declaration of the functor that converts betwen the Recursive +//class and the hook +struct Functor +{ + //Required types + typedef list_member_hook<> hook_type; + typedef hook_type* hook_ptr; + typedef const hook_type* const_hook_ptr; + typedef Recursive value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + //Required static functions + static hook_ptr to_hook_ptr (value_type &value); + static const_hook_ptr to_hook_ptr(const value_type &value); + static pointer to_value_ptr(hook_ptr n); + static const_pointer to_value_ptr(const_hook_ptr n); +}; + +//Define the recursive class +class Recursive +{ + private: + Recursive(const Recursive&); + Recursive & operator=(const Recursive&); + + public: + Recursive() : hook(), children() {} + list_member_hook<> hook; + list< Recursive, function_hook< Functor> > children; +}; + +//Definition of Functor functions +inline Functor::hook_ptr Functor::to_hook_ptr (Functor::value_type &value) + { return &value.hook; } +inline Functor::const_hook_ptr Functor::to_hook_ptr(const Functor::value_type &value) + { return &value.hook; } +inline Functor::pointer Functor::to_value_ptr(Functor::hook_ptr n) + { return get_parent_from_member(n, &Recursive::hook); } +inline Functor::const_pointer Functor::to_value_ptr(Functor::const_hook_ptr n) + { return get_parent_from_member(n, &Recursive::hook); } + +int main() +{ + Recursive f, f2; + //A recursive list of Recursive + list< Recursive, function_hook< Functor> > l; + + //Insert a node in parent list + l.insert(l.begin(), f); + + //Insert a node in child list + l.begin()->children.insert(l.begin()->children.begin(), f2); + + //Objects properly inserted + assert(l.size() == l.begin()->children.size()); + assert(l.size() == 1); + + //Clear both lists + l.begin()->children.clear(); + l.clear(); + return 0; +} +//] + +#include diff --git a/proj/vc7ide/Intrusive.sln b/proj/vc7ide/Intrusive.sln index 4726fdc..3192a45 100644 --- a/proj/vc7ide/Intrusive.sln +++ b/proj/vc7ide/Intrusive.sln @@ -91,13 +91,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "treap_multiset", "treap_mul ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recursive", "recursive\recursive.vcproj", "{7679B41B-F2B4-9176-CB81-35449467B435}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "function_hook", "function_hook\function_hook.vcproj", "{761A79B4-9968-CB81-F02B-2A4497345475}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.ActiveCfg = Debug|Win32 {977B61B4-9968-497C-9F0B-24A8145473B8}.Debug.Build.0 = Debug|Win32 @@ -191,6 +197,14 @@ Global {16E09E95-F4A2-C971-BC76-9BA407191C59}.Debug.Build.0 = Debug|Win32 {16E09E95-F4A2-C971-BC76-9BA407191C59}.Release.ActiveCfg = Release|Win32 {16E09E95-F4A2-C971-BC76-9BA407191C59}.Release.Build.0 = Release|Win32 + {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.ActiveCfg = Debug|Win32 + {7679B41B-F2B4-9176-CB81-35449467B435}.Debug.Build.0 = Debug|Win32 + {7679B41B-F2B4-9176-CB81-35449467B435}.Release.ActiveCfg = Release|Win32 + {7679B41B-F2B4-9176-CB81-35449467B435}.Release.Build.0 = Release|Win32 + {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.ActiveCfg = Debug|Win32 + {761A79B4-9968-CB81-F02B-2A4497345475}.Debug.Build.0 = Debug|Win32 + {761A79B4-9968-CB81-F02B-2A4497345475}.Release.ActiveCfg = Release|Win32 + {761A79B4-9968-CB81-F02B-2A4497345475}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj index 8501d3b..d7f2673 100644 --- a/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj +++ b/proj/vc7ide/_intrusivelib/_intrusivelib.vcproj @@ -156,6 +156,9 @@ + + @@ -373,6 +376,9 @@ + + @@ -394,6 +400,12 @@ + + + + diff --git a/proj/vc7ide/any_test/any_test.vcproj b/proj/vc7ide/any_test/any_test.vcproj index e99365d..b053349 100644 --- a/proj/vc7ide/any_test/any_test.vcproj +++ b/proj/vc7ide/any_test/any_test.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/avl_multiset/avl_multiset.vcproj b/proj/vc7ide/avl_multiset/avl_multiset.vcproj index a2d2cb1..2a80b81 100644 --- a/proj/vc7ide/avl_multiset/avl_multiset.vcproj +++ b/proj/vc7ide/avl_multiset/avl_multiset.vcproj @@ -25,7 +25,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/avl_set/avl_set.vcproj b/proj/vc7ide/avl_set/avl_set.vcproj index e5df0b2..9ecd59d 100644 --- a/proj/vc7ide/avl_set/avl_set.vcproj +++ b/proj/vc7ide/avl_set/avl_set.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj b/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj index 2c873b8..a396174 100644 --- a/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj +++ b/proj/vc7ide/custom_bucket_traits/custom_bucket_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/default_hook/default_hook.vcproj b/proj/vc7ide/default_hook/default_hook.vcproj index e6c1b7f..9c26fb7 100644 --- a/proj/vc7ide/default_hook/default_hook.vcproj +++ b/proj/vc7ide/default_hook/default_hook.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/external_value_traits/external_value_traits.vcproj b/proj/vc7ide/external_value_traits/external_value_traits.vcproj index 6f0b875..87ebd51 100644 --- a/proj/vc7ide/external_value_traits/external_value_traits.vcproj +++ b/proj/vc7ide/external_value_traits/external_value_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/function_hook/function_hook.vcproj b/proj/vc7ide/function_hook/function_hook.vcproj new file mode 100644 index 0000000..0fd863c --- /dev/null +++ b/proj/vc7ide/function_hook/function_hook.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/list/list.vcproj b/proj/vc7ide/list/list.vcproj index 8f5817b..e5e510b 100644 --- a/proj/vc7ide/list/list.vcproj +++ b/proj/vc7ide/list/list.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/make_functions/make_functions.vcproj b/proj/vc7ide/make_functions/make_functions.vcproj index 572aa02..cf926ce 100644 --- a/proj/vc7ide/make_functions/make_functions.vcproj +++ b/proj/vc7ide/make_functions/make_functions.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/multiset/multiset.vcproj b/proj/vc7ide/multiset/multiset.vcproj index 8828607..423d48e 100644 --- a/proj/vc7ide/multiset/multiset.vcproj +++ b/proj/vc7ide/multiset/multiset.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/recursive/recursive.vcproj b/proj/vc7ide/recursive/recursive.vcproj new file mode 100644 index 0000000..1e4b6db --- /dev/null +++ b/proj/vc7ide/recursive/recursive.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/set/set.vcproj b/proj/vc7ide/set/set.vcproj index 85dff59..f7a9976 100644 --- a/proj/vc7ide/set/set.vcproj +++ b/proj/vc7ide/set/set.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/sg_multiset/sg_multiset.vcproj b/proj/vc7ide/sg_multiset/sg_multiset.vcproj index fab36dc..b14f697 100644 --- a/proj/vc7ide/sg_multiset/sg_multiset.vcproj +++ b/proj/vc7ide/sg_multiset/sg_multiset.vcproj @@ -25,7 +25,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/sg_set/sg_set.vcproj b/proj/vc7ide/sg_set/sg_set.vcproj index 222fffc..7910d1b 100644 --- a/proj/vc7ide/sg_set/sg_set.vcproj +++ b/proj/vc7ide/sg_set/sg_set.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/slist/slist.vcproj b/proj/vc7ide/slist/slist.vcproj index 3d118f5..14d5ca7 100644 --- a/proj/vc7ide/slist/slist.vcproj +++ b/proj/vc7ide/slist/slist.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/splay_multiset/splay_multiset.vcproj b/proj/vc7ide/splay_multiset/splay_multiset.vcproj index 8239a8f..3bbce26 100644 --- a/proj/vc7ide/splay_multiset/splay_multiset.vcproj +++ b/proj/vc7ide/splay_multiset/splay_multiset.vcproj @@ -25,7 +25,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/splay_set/splay_set.vcproj b/proj/vc7ide/splay_set/splay_set.vcproj index 63a9d43..2bccaa2 100644 --- a/proj/vc7ide/splay_set/splay_set.vcproj +++ b/proj/vc7ide/splay_set/splay_set.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj b/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj index a5b898e..72cbe3b 100644 --- a/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj +++ b/proj/vc7ide/stateful_value_traits/stateful_value_traits.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/to-do.txt b/proj/vc7ide/to-do.txt index 6cda9e3..4a5777f 100644 --- a/proj/vc7ide/to-do.txt +++ b/proj/vc7ide/to-do.txt @@ -14,3 +14,4 @@ -> Non-array buckets -> Document incremental<> option better -> Assure stable order for optimize_multikey and inverse order otherwise +-> add an option to unordered containers to get O(1) traversal and begin()/end() even with very low load factors diff --git a/proj/vc7ide/treap_multiset/treap_multiset.vcproj b/proj/vc7ide/treap_multiset/treap_multiset.vcproj index b0b1edd..af29eb2 100644 --- a/proj/vc7ide/treap_multiset/treap_multiset.vcproj +++ b/proj/vc7ide/treap_multiset/treap_multiset.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/treap_set/treap_set.vcproj b/proj/vc7ide/treap_set/treap_set.vcproj index a6d68a3..5d438fe 100644 --- a/proj/vc7ide/treap_set/treap_set.vcproj +++ b/proj/vc7ide/treap_set/treap_set.vcproj @@ -24,7 +24,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/unordered_multiset/unordered_multiset.vcproj b/proj/vc7ide/unordered_multiset/unordered_multiset.vcproj index 2559e0c..2a8ec4a 100644 --- a/proj/vc7ide/unordered_multiset/unordered_multiset.vcproj +++ b/proj/vc7ide/unordered_multiset/unordered_multiset.vcproj @@ -25,7 +25,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/unordered_set/unordered_set.vcproj b/proj/vc7ide/unordered_set/unordered_set.vcproj index 1496175..a3bb584 100644 --- a/proj/vc7ide/unordered_set/unordered_set.vcproj +++ b/proj/vc7ide/unordered_set/unordered_set.vcproj @@ -25,7 +25,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/proj/vc7ide/virtual_base/virtual_base.vcproj b/proj/vc7ide/virtual_base/virtual_base.vcproj index 7d87163..b5f6f66 100644 --- a/proj/vc7ide/virtual_base/virtual_base.vcproj +++ b/proj/vc7ide/virtual_base/virtual_base.vcproj @@ -27,7 +27,7 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="5" - DisableLanguageExtensions="TRUE" + DisableLanguageExtensions="FALSE" TreatWChar_tAsBuiltInType="TRUE" ForceConformanceInForLoopScope="TRUE" UsePrecompiledHeader="0" diff --git a/test/function_hook_test.cpp b/test/function_hook_test.cpp new file mode 100644 index 0000000..5b9e570 --- /dev/null +++ b/test/function_hook_test.cpp @@ -0,0 +1,152 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2010 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +struct MyClass +{ + MyClass() : order(0) {} + int order; + + //This internal type has two hooks + struct InnerNode : public list_base_hook<>, public slist_base_hook<> + , public set_base_hook<>, public unordered_set_base_hook<> + { + list_member_hook<> listhook; + slist_member_hook<> slisthook; + set_member_hook<> sethook; + unordered_set_member_hook<> usethook; + } inner; + + friend bool operator < (const MyClass &l, const MyClass &r) + { return l.order < r.order; } + friend bool operator == (const MyClass &l, const MyClass &r) + { return l.order == r.order; } + friend std::size_t hash_value(const MyClass &value) + { return std::size_t(value.order); } +}; + +//This functor converts between MyClass and the InnerNode member hook +#define InnerMemberHook(TAG, HOOKTYPE, MEMBERNAME)\ + struct InnerMemberHookFunctor##TAG \ + {\ + typedef HOOKTYPE hook_type;\ + typedef hook_type* hook_ptr;\ + typedef const hook_type* const_hook_ptr;\ + typedef MyClass value_type;\ + typedef value_type* pointer;\ + typedef const value_type* const_pointer;\ + \ + static hook_ptr to_hook_ptr (value_type &value)\ + { return &value.inner.MEMBERNAME; }\ + static const_hook_ptr to_hook_ptr(const value_type &value)\ + { return &value.inner.MEMBERNAME; }\ + static pointer to_value_ptr(hook_ptr n)\ + {\ + return get_parent_from_member\ + (get_parent_from_member(n, &MyClass::InnerNode::MEMBERNAME)\ + ,&MyClass::inner\ + );\ + }\ + static const_pointer to_value_ptr(const_hook_ptr n)\ + {\ + return get_parent_from_member\ + (get_parent_from_member(n, &MyClass::InnerNode::MEMBERNAME)\ + ,&MyClass::inner\ + );\ + }\ + };\ +// + + +//This functor converts between MyClass and the InnerNode base hook +#define InnerBaseHook(TAG, HOOKTYPE)\ + struct InnerBaseHookFunctor##TAG \ + {\ + typedef HOOKTYPE hook_type;\ + typedef hook_type* hook_ptr;\ + typedef const hook_type* const_hook_ptr;\ + typedef MyClass value_type;\ + typedef value_type* pointer;\ + typedef const value_type* const_pointer;\ + \ + static hook_ptr to_hook_ptr (value_type &value)\ + { return &value.inner; }\ + static const_hook_ptr to_hook_ptr(const value_type &value)\ + { return &value.inner; }\ + static pointer to_value_ptr(hook_ptr n)\ + {\ + return get_parent_from_member(static_cast(n),&MyClass::inner);\ + }\ + static const_pointer to_value_ptr(const_hook_ptr n)\ + {\ + return get_parent_from_member(static_cast(n),&MyClass::inner);\ + }\ + };\ +// + +//List +InnerMemberHook(List, list_member_hook<>, listhook) +InnerBaseHook(List, list_base_hook<>) +//Slist +InnerMemberHook(Slist, slist_member_hook<>, slisthook) +InnerBaseHook(Slist, slist_base_hook<>) +//Set +InnerMemberHook(Set, set_member_hook<>, sethook) +InnerBaseHook(Set, set_base_hook<>) +//Unordered Set +InnerMemberHook(USet, unordered_set_member_hook<>, usethook) +InnerBaseHook(USet, unordered_set_base_hook<>) + +//Define containers +typedef list < MyClass, function_hook< InnerMemberHookFunctorList> > CustomListMember; +typedef list < MyClass, function_hook< InnerBaseHookFunctorList > > CustomListBase; +typedef slist< MyClass, function_hook< InnerMemberHookFunctorSlist> > CustomSlistMember; +typedef slist< MyClass, function_hook< InnerBaseHookFunctorSlist > > CustomSlistBase; +typedef set < MyClass, function_hook< InnerMemberHookFunctorSet> > CustomSetMember; +typedef set < MyClass, function_hook< InnerBaseHookFunctorSet > > CustomSetBase; +typedef unordered_set< MyClass, function_hook< InnerMemberHookFunctorUSet> > CustomUSetMember; +typedef unordered_set< MyClass, function_hook< InnerBaseHookFunctorUSet > > CustomUSetBase; + +int main() +{ + MyClass n; + CustomListBase listbase; + CustomListMember listmember; + CustomSlistBase slistbase; + CustomSlistMember slistmember; + CustomSetBase setbase; + CustomSetMember setmember; + CustomUSetBase::bucket_type buckets[1]; + CustomUSetBase usetbase(CustomUSetBase::bucket_traits(buckets, 1)); + CustomUSetMember usetmember(CustomUSetMember::bucket_traits(buckets, 1)); + + listbase.insert(listbase.begin(), n); + listmember.insert(listmember.begin(), n); + slistbase.insert(slistbase.begin(), n); + slistmember.insert(slistmember.begin(), n); + setbase.insert(n); + setmember.insert(n); + usetbase.insert(n); + usetmember.insert(n); + + return 0; +} + +#include diff --git a/test/generic_assoc_test.hpp b/test/generic_assoc_test.hpp index 5d10d72..7ff75f7 100644 --- a/test/generic_assoc_test.hpp +++ b/test/generic_assoc_test.hpp @@ -402,9 +402,9 @@ void test_generic_assoc::test_insert_before for(vec_iterator it(--values.end()); true; --it){ testset.push_front(*it); - if(it == values.begin()){ + if(it == values.begin()){ break; - } + } } BOOST_TEST(testset.size() == values.size()); TEST_INTRUSIVE_SEQUENCE_EXPECTED(values, testset.begin()); diff --git a/test/list_test.cpp b/test/list_test.cpp index e9f8b74..b55ec08 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -10,10 +10,8 @@ // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// - #include #include - #include #include "itestvalue.hpp" #include "smart_ptr.hpp" @@ -500,4 +498,3 @@ int main( int, char* [] ) return boost::report_errors(); } -#include diff --git a/test/recursive_test.cpp b/test/recursive_test.cpp new file mode 100644 index 0000000..c72316b --- /dev/null +++ b/test/recursive_test.cpp @@ -0,0 +1,71 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2010 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +typedef list_base_hook<> ListBaseHook; +typedef slist_base_hook<> SListBaseHook; +typedef set_base_hook<> SetBaseHook; +typedef unordered_set_base_hook<> USetBaseHook; + +class Foo; +typedef unordered_set > USet; + +class Foo : public ListBaseHook, public SListBaseHook, public SetBaseHook, public USetBaseHook +{ + USet::bucket_type buckets[1]; + Foo(const Foo &); + Foo & operator=(const Foo &); + + public: + Foo() : uset_children(USet::bucket_traits(buckets, 1)) + {} + list > list_children; + slist > slist_children; + set > set_children; + USet uset_children; +}; + +void instantiate() +{ + list< Foo, base_hook > list_; list_.clear(); + slist< Foo, base_hook > slist_; slist_.clear(); + set< Foo, base_hook > set_; set_.clear(); + + USet::bucket_type buckets[1]; + USet unordered_set_(USet::bucket_traits(buckets, 1)); unordered_set_.clear(); +} +int main() +{ + instantiate(); + + //A small test with list + { + Foo f, f2; + list< Foo, base_hook > l; + l.insert(l.begin(), f); + l.begin()->list_children.insert(l.begin()->list_children.begin(), f2); + assert(l.size() == l.begin()->list_children.size()); + l.begin()->list_children.clear(); + l.clear(); + } + return 0; +} diff --git a/test/smart_ptr.hpp b/test/smart_ptr.hpp index c5ccfc5..6965eab 100644 --- a/test/smart_ptr.hpp +++ b/test/smart_ptr.hpp @@ -13,6 +13,7 @@ #include #include +#include #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -312,7 +313,7 @@ inline T* boost_intrusive_get_pointer(const smart_ptr & p) //!Simulation of static_cast between pointers. Never throws. template inline smart_ptr - static_pointer_cast(smart_ptr const & r) + static_pointer_cast(const smart_ptr & r) { return smart_ptr(r, detail::static_cast_tag()); } From 4df267385144e209b3cc0ba22e53035893d0e588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 24 Aug 2010 17:26:36 +0000 Subject: [PATCH 28/29] More changes for Boost 1.45 [SVN r64985] --- .../intrusive/circular_slist_algorithms.hpp | 2 +- .../intrusive/derivation_value_traits.hpp | 15 +++- .../detail/any_node_and_algorithms.hpp | 6 +- .../boost/intrusive/detail/hashtable_node.hpp | 9 +- .../intrusive/detail/parent_from_member.hpp | 12 ++- include/boost/intrusive/detail/utilities.hpp | 62 +++++++++++--- include/boost/intrusive/hashtable.hpp | 23 ++--- include/boost/intrusive/intrusive_fwd.hpp | 83 +++++++++++-------- include/boost/intrusive/options.hpp | 18 ++++ .../boost/intrusive/parent_from_member.hpp | 42 ++++++++++ include/boost/intrusive/rbtree_algorithms.hpp | 7 ++ .../boost/intrusive/unordered_set_hook.hpp | 8 +- 12 files changed, 216 insertions(+), 71 deletions(-) create mode 100644 include/boost/intrusive/parent_from_member.hpp diff --git a/include/boost/intrusive/circular_slist_algorithms.hpp b/include/boost/intrusive/circular_slist_algorithms.hpp index ae06396..8bb95cd 100644 --- a/include/boost/intrusive/circular_slist_algorithms.hpp +++ b/include/boost/intrusive/circular_slist_algorithms.hpp @@ -63,7 +63,7 @@ class circular_slist_algorithms //! Effects: Constructs an non-used list element, putting the next //! pointer to null: - //! NodeTraits::get_next(this_node) == 0 + //! NodeTraits::get_next(this_node) == 0 //! //! Complexity: Constant //! diff --git a/include/boost/intrusive/derivation_value_traits.hpp b/include/boost/intrusive/derivation_value_traits.hpp index 6ae28a3..8711d56 100644 --- a/include/boost/intrusive/derivation_value_traits.hpp +++ b/include/boost/intrusive/derivation_value_traits.hpp @@ -14,6 +14,7 @@ #define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP #include +#include #include namespace boost { @@ -44,10 +45,20 @@ struct derivation_value_traits { return node_ptr(&value); } static pointer to_value_ptr(node_ptr n) - { return pointer(static_cast(detail::boost_intrusive_get_pointer(n))); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(n)); + return pointer(&static_cast(*n)); + } static const_pointer to_value_ptr(const_node_ptr n) - { return const_pointer(static_cast(detail::boost_intrusive_get_pointer(n))); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(n)); + return const_pointer(&static_cast(*n)); + } }; } //namespace intrusive diff --git a/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/include/boost/intrusive/detail/any_node_and_algorithms.hpp index e2fbbfa..513bdd9 100644 --- a/include/boost/intrusive/detail/any_node_and_algorithms.hpp +++ b/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace boost { namespace intrusive { @@ -87,7 +88,10 @@ struct any_unordered_node_traits static const bool optimize_multikey = true; static node_ptr get_next(const_node_ptr n) - { return node_ptr(&static_cast(*n->node_ptr_1)); } + { + using ::boost::static_pointer_cast; + return static_pointer_cast(n->node_ptr_1); + } static void set_next(node_ptr n, node_ptr next) { n->node_ptr_1 = next; } diff --git a/include/boost/intrusive/detail/hashtable_node.hpp b/include/boost/intrusive/detail/hashtable_node.hpp index a077155..72188b9 100644 --- a/include/boost/intrusive/detail/hashtable_node.hpp +++ b/include/boost/intrusive/detail/hashtable_node.hpp @@ -22,7 +22,7 @@ #include #include //remove-me #include - +#include namespace boost { namespace intrusive { namespace detail { @@ -118,7 +118,12 @@ class hashtable_iterator typedef typename Container::size_type size_type; static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p) - { return typename Container::node_ptr(&static_cast(*p)); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(p); + return typename Container::node_ptr(&static_cast(*p)); + } public: typedef typename Container::value_type value_type; diff --git a/include/boost/intrusive/detail/parent_from_member.hpp b/include/boost/intrusive/detail/parent_from_member.hpp index 0b30867..c06d932 100644 --- a/include/boost/intrusive/detail/parent_from_member.hpp +++ b/include/boost/intrusive/detail/parent_from_member.hpp @@ -9,8 +9,8 @@ // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP -#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP +#ifndef BOOST_INTRUSIVE_DETAIL_PARENT_FROM_MEMBER_HPP +#define BOOST_INTRUSIVE_DETAIL_PARENT_FROM_MEMBER_HPP #include #include @@ -47,15 +47,13 @@ inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_t template inline Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member) { - return (Parent*)((char*)member - - offset_from_pointer_to_member(ptr_to_member)); + return (Parent*)((char*)member - offset_from_pointer_to_member(ptr_to_member)); } template inline const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member) { - return (const Parent*)((const char*)member - - offset_from_pointer_to_member(ptr_to_member)); + return (const Parent*)((const char*)member - offset_from_pointer_to_member(ptr_to_member)); } } //namespace detail { @@ -68,4 +66,4 @@ inline const Parent *parent_from_member(const Member *member, const Member Paren #include -#endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP +#endif //#ifndef BOOST_INTRUSIVE_DETAIL_PARENT_FROM_MEMBER_HPP diff --git a/include/boost/intrusive/detail/utilities.hpp b/include/boost/intrusive/detail/utilities.hpp index a9b876b..064ff6e 100644 --- a/include/boost/intrusive/detail/utilities.hpp +++ b/include/boost/intrusive/detail/utilities.hpp @@ -410,14 +410,10 @@ struct member_hook_traits static const link_mode_type link_mode = Hook::boost_intrusive_tags::link_mode; static node_ptr to_node_ptr(reference value) - { - return reinterpret_cast(&(value.*P)); - } + { return static_cast(&(value.*P)); } static const_node_ptr to_node_ptr(const_reference value) - { - return static_cast(&(value.*P)); - } + { return static_cast(&(value.*P)); } static pointer to_value_ptr(node_ptr n) { @@ -432,6 +428,45 @@ struct member_hook_traits } }; +template +struct function_hook_traits +{ + public: + typedef typename Functor::hook_type hook_type; + typedef typename Functor::hook_ptr hook_ptr; + typedef typename Functor::const_hook_ptr const_hook_ptr; + typedef typename hook_type::boost_intrusive_tags::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename Functor::value_type value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename boost::pointer_to_other::type pointer; + typedef typename boost::pointer_to_other::type const_pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + static const link_mode_type link_mode = hook_type::boost_intrusive_tags::link_mode; + + static node_ptr to_node_ptr(reference value) + { return static_cast(&*Functor::to_hook_ptr(value)); } + + static const_node_ptr to_node_ptr(const_reference value) + { return static_cast(&*Functor::to_hook_ptr(value)); } + + static pointer to_value_ptr(node_ptr n) + { return Functor::to_value_ptr(to_hook_ptr(n)); } + + static const_pointer to_value_ptr(const_node_ptr n) + { return Functor::to_value_ptr(to_hook_ptr(n)); } + + private: + static hook_ptr to_hook_ptr(node_ptr n) + { return hook_ptr(&*static_cast(&*n)); } + + static const_hook_ptr to_hook_ptr(const_node_ptr n) + { return const_hook_ptr(&*static_cast(&*n)); } +}; + + //This function uses binary search to discover the //highest set bit of the integer inline std::size_t floor_log2 (std::size_t x) @@ -454,14 +489,19 @@ inline std::size_t floor_log2 (std::size_t x) inline float fast_log2 (float val) { - boost::uint32_t * exp_ptr = - static_cast(static_cast(&val)); - boost::uint32_t x = *exp_ptr; + union caster_t + { + boost::uint32_t x; + float val; + } caster; + + caster.val = val; + boost::uint32_t x = caster.x; const int log_2 = (int)(((x >> 23) & 255) - 128); x &= ~(255 << 23); x += 127 << 23; - *exp_ptr = x; - + caster.x = x; + val = caster.val; val = ((-1.0f/3) * val + 2) * val - 2.0f/3; return (val + log_2); diff --git a/include/boost/intrusive/hashtable.hpp b/include/boost/intrusive/hashtable.hpp index 99de70d..1493eac 100644 --- a/include/boost/intrusive/hashtable.hpp +++ b/include/boost/intrusive/hashtable.hpp @@ -23,6 +23,7 @@ #include #include #include +#include //General intrusive utilities #include #include @@ -157,26 +158,22 @@ struct get_slist_impl_from_supposed_value_traits template struct unordered_bucket_impl { - /// @cond typedef typename get_slist_impl_from_supposed_value_traits ::type slist_impl; typedef detail::bucket_impl implementation_defined; - /// @endcond typedef implementation_defined type; }; template struct unordered_bucket_ptr_impl { - /// @cond typedef typename detail::get_node_traits ::type::node_ptr node_ptr; typedef typename unordered_bucket_impl ::type bucket_type; typedef typename boost::pointer_to_other ::type implementation_defined; - /// @endcond typedef implementation_defined type; }; @@ -329,7 +326,12 @@ struct group_functions typedef circular_slist_algorithms group_algorithms; static node_ptr dcast_bucket_ptr(slist_node_ptr p) - { return node_ptr(&static_cast(*p)); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(p); + return node_ptr(&static_cast(*p)); + } static slist_node_ptr priv_get_bucket_before_begin (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p) @@ -496,7 +498,6 @@ struct unordered_bucket_ptr template struct unordered_default_bucket_traits { - /// @cond typedef typename ValueTraitsOrHookOption:: template pack::value_traits supposed_value_traits; typedef typename detail:: @@ -504,7 +505,6 @@ struct unordered_default_bucket_traits ::type slist_impl; typedef detail::bucket_traits_impl implementation_defined; - /// @endcond typedef implementation_defined type; }; @@ -2322,7 +2322,12 @@ class hashtable_impl } static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p) - { return node_ptr(&static_cast(*p)); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(p); + return node_ptr(&static_cast(*p)); + } 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)); } @@ -2889,7 +2894,6 @@ struct make_hashtable_opt //Real value traits must be calculated from options typedef typename detail::get_value_traits ::type value_traits; - /// @cond static const bool external_value_traits = detail::external_value_traits_is_true::value; typedef typename detail::eval_if_c @@ -2898,7 +2902,6 @@ struct make_hashtable_opt , detail::identity >::type real_value_traits; typedef typename packed_options::bucket_traits specified_bucket_traits; - /// @endcond //Real bucket traits must be calculated from options and calculated value_traits typedef typename detail::get_slist_impl diff --git a/include/boost/intrusive/intrusive_fwd.hpp b/include/boost/intrusive/intrusive_fwd.hpp index 7c9b2a1..dc18566 100644 --- a/include/boost/intrusive/intrusive_fwd.hpp +++ b/include/boost/intrusive/intrusive_fwd.hpp @@ -50,7 +50,7 @@ class rbtree_algorithms; //////////////////////////// //slist -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -64,7 +64,7 @@ template #endif class slist; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -75,7 +75,7 @@ template #endif class slist_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -87,7 +87,7 @@ template class slist_member_hook; //list -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -99,7 +99,7 @@ template #endif class list; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -110,7 +110,7 @@ template #endif class list_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -121,8 +121,19 @@ template #endif class list_member_hook; +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) +template + < class O1 = none + , class O2 = none + , class O3 = none + > +#else +template +#endif +class list_hook; + //rbtree/set/multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -135,7 +146,7 @@ template #endif class rbtree; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -148,7 +159,7 @@ template #endif class set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -161,7 +172,7 @@ template #endif class multiset; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -173,7 +184,7 @@ template #endif class set_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -186,7 +197,7 @@ template class set_member_hook; //splaytree/splay_set/splay_multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -199,7 +210,7 @@ template #endif class splaytree; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -212,7 +223,7 @@ template #endif class splay_set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -225,7 +236,7 @@ template #endif class splay_multiset; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -236,7 +247,7 @@ template #endif class splay_set_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -248,7 +259,7 @@ template class splay_set_member_hook; //avltree/avl_set/avl_multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -261,7 +272,7 @@ template #endif class avltree; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -274,7 +285,7 @@ template #endif class avl_set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -287,7 +298,7 @@ template #endif class avl_multiset; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -299,7 +310,7 @@ template #endif class avl_set_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -313,7 +324,7 @@ class avl_set_member_hook; //treap/treap_set/treap_multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -326,7 +337,7 @@ template #endif class treap; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -339,7 +350,7 @@ template #endif class treap_set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -357,7 +368,7 @@ template struct priority_compare; //sgtree/sg_set/sg_multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -370,7 +381,7 @@ template #endif class sgtree; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -383,7 +394,7 @@ template #endif class sg_set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -396,7 +407,7 @@ template #endif class sg_multiset; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -407,7 +418,7 @@ template #endif class bs_set_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -420,7 +431,7 @@ class bs_set_member_hook; //hashtable/unordered_set/unordered_multiset -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -439,7 +450,7 @@ template #endif class hashtable; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -458,7 +469,7 @@ template #endif class unordered_set; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class T , class O1 = none @@ -477,7 +488,7 @@ template #endif class unordered_multiset; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -489,7 +500,7 @@ template #endif class unordered_set_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -501,7 +512,7 @@ template #endif class unordered_set_member_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none @@ -512,7 +523,7 @@ template #endif class any_base_hook; -#ifndef BOOST_INTRUSIVE_VARIADIC_TEMPLATES +#if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) && !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) template < class O1 = none , class O2 = none diff --git a/include/boost/intrusive/options.hpp b/include/boost/intrusive/options.hpp index d692b1e..9731651 100644 --- a/include/boost/intrusive/options.hpp +++ b/include/boost/intrusive/options.hpp @@ -343,6 +343,24 @@ struct member_hook }; +//!This option setter specifies the function object that will +//!be used to convert between values to be inserted in a container +//!and the hook to be used for that purpose. +template< typename Functor> +struct function_hook +{ +/// @cond + typedef detail::function_hook_traits + function_value_traits; + template + struct pack : Base + { + typedef function_value_traits value_traits; + }; +/// @endcond +}; + + //!This option setter specifies that the container //!must use the specified base hook template diff --git a/include/boost/intrusive/parent_from_member.hpp b/include/boost/intrusive/parent_from_member.hpp new file mode 100644 index 0000000..882c073 --- /dev/null +++ b/include/boost/intrusive/parent_from_member.hpp @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2010-2010 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP +#define BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP + +#include +#include + +namespace boost { +namespace intrusive { + +//! Given a pointer to a member and its corresponding pointer to data member, +//! this function returns the pointer of the parent containing that member. +//! Note: this function does not work with pointer to members that rely on +//! virtual inheritance. +template +inline Parent *get_parent_from_member(Member *member, const Member Parent::* ptr_to_member) +{ return ::boost::intrusive::detail::parent_from_member(member, ptr_to_member); } + +//! Given a const pointer to a member and its corresponding const pointer to data member, +//! this function returns the const pointer of the parent containing that member. +//! Note: this function does not work with pointer to members that rely on +//! virtual inheritance. +template +inline const Parent *get_parent_from_member(const Member *member, const Member Parent::* ptr_to_member) +{ return ::boost::intrusive::detail::parent_from_member(member, ptr_to_member); } + +} //namespace intrusive { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTRUSIVE_GET_PARENT_FROM_MEMBER_HPP diff --git a/include/boost/intrusive/rbtree_algorithms.hpp b/include/boost/intrusive/rbtree_algorithms.hpp index 89abcd6..a470a5d 100644 --- a/include/boost/intrusive/rbtree_algorithms.hpp +++ b/include/boost/intrusive/rbtree_algorithms.hpp @@ -57,6 +57,9 @@ #include #include +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#pragma optimize( "g", off ) +#endif namespace boost { namespace intrusive { @@ -905,6 +908,10 @@ class rbtree_algorithms } //namespace intrusive } //namespace boost +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#pragma optimize( "", on ) +#endif + #include #endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP diff --git a/include/boost/intrusive/unordered_set_hook.hpp b/include/boost/intrusive/unordered_set_hook.hpp index 286b318..61f4a72 100644 --- a/include/boost/intrusive/unordered_set_hook.hpp +++ b/include/boost/intrusive/unordered_set_hook.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -76,7 +77,12 @@ struct unordered_node_traits static const bool optimize_multikey = OptimizeMultiKey; static node_ptr get_next(const_node_ptr n) - { return node_ptr(&static_cast(*n->next_)); } + { +// This still fails in gcc < 4.4 so forget about it +// using ::boost::static_pointer_cast; +// return static_pointer_cast(n->next_); + return node_ptr(&static_cast(*n->next_)); + } static void set_next(node_ptr n, node_ptr next) { n->next_ = next; } From 41da46b4d34664104a5ccf6a3dc38f4485250937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 26 Aug 2010 06:56:37 +0000 Subject: [PATCH 29/29] Fix MingW linker errors [SVN r65006] --- example/Jamfile.v2 | 4 ++++ test/Jamfile.v2 | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index cfd371d..792692f 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -25,6 +25,10 @@ rule test_all : # additional args : # test-files : # requirements + acc:-lrt + acc-pa_risc:-lrt + gcc-mingw:"-lole32 -loleaut32" + hpux,gcc:"-Wl,+as,mpas" ] ; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d56b50a..49704d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,10 +20,14 @@ rule test_all for local fileb in [ glob *.cpp ] { - all_rules += [ run $(fileb) + all_rules += [ run $(fileb) /boost/thread//boost_thread : # additional args : # test-files : # requirements + acc:-lrt + acc-pa_risc:-lrt + gcc-mingw:"-lole32 -loleaut32" + hpux,gcc:"-Wl,+as,mpas" ] ; }