multi_index_containerContents
-Ranked indices
-
-
-Ordered indices are implemented using red-black trees; these trees
-can be augmented with additional information to obtain a type
-of data structure called
-order-statistics
-trees, allowing for logarithmic search of the n-th element. It
-has been proposed that order-statistics trees be used to devise a new type of
-ranked indices that support operator[]
while retaining
-the functionality of ordered indices.
-
-
Notifying indices
@@ -200,9 +186,9 @@ Release notes
-
Revised July 6th 2013
+Revised April 19th 2015
-© Copyright 2003-2013 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/index.html b/doc/index.html
index 4e89487..b86dca5 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -31,12 +31,13 @@ borrowed from relational database terminology and allows for the specification o
complex data structures in the spirit of multiply indexed relational tables where
simple sets and maps are not enough. A wide selection of indices is provided,
modeled after analogous STL containers like std::set
,
-std::list
and hashed sets.
+std::list
and std::unordered_set
.
Boost.MultiIndex features additional functionalities, like subobject searching,
-range querying and in-place updating of elements, which make it a convenient replacement
+range querying, in-place updating of elements and calculation of ranks,
+which make it a convenient replacement
for std::set
and set::multiset
even when no multi-indexing
capabilities are needed.
@@ -85,9 +86,9 @@ Tutorial
-Revised November 30th 2013
+Revised April 19th 2015
-© Copyright 2003-2013 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/reference/hash_indices.html b/doc/reference/hash_indices.html
index c4d127a..bfff9ca 100644
--- a/doc/reference/hash_indices.html
+++ b/doc/reference/hash_indices.html
@@ -15,8 +15,8 @@
Boost.MultiIndex Hashed indices reference
-
-Ordered indices
+

Boost.MultiIndex reference
@@ -1117,8 +1117,8 @@ and the restored it'
a local_iterator
, or viceversa.
-
-Ordered indices
+

Boost.MultiIndex reference
@@ -1129,9 +1129,9 @@ Sequenced indices
-Revised August 20th 2014
+Revised April 19th 2015
-© Copyright 2003-2014 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/reference/index.html b/doc/reference/index.html
index 8525dba..7661e50 100644
--- a/doc/reference/index.html
+++ b/doc/reference/index.html
@@ -34,6 +34,7 @@ Index
Class template multi_index_container
Index reference
Ordered indices
+ Ranked indices
Hashed indices
Sequenced indices
Random access indices
@@ -59,6 +60,13 @@ The following dependencies among headers of Boost.MultiIndex hold:
"boost/multi_index/tag.hpp"
.
+
+ "boost/multi_index/ranked_index.hpp"
includes
+
+
"boost/multi_index/hashed_index.hpp"
includes
@@ -127,9 +135,9 @@ Index
-Revised June 19th 2007
+Revised April 19th 2015
-© Copyright 2003-2007 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/reference/indices.html b/doc/reference/indices.html
index 75995f9..a561199 100644
--- a/doc/reference/indices.html
+++ b/doc/reference/indices.html
@@ -189,11 +189,14 @@ index specifiers
ordered_unique
and
ordered_non_unique
for
ordered indices,
+ ranked_unique
and
+ ranked_non_unique
for
+ ranked indices,
hashed_unique
and
hashed_non_unique
for
hashed indices,
sequenced
for
- sequenced indices
+ sequenced indices,
and random_access
for
random access indices.
@@ -310,6 +313,10 @@ reference.
- Ordered indices sort the elements
on the key and provide fast lookup capabilites.
+ - Ranked indices are a variation of
+ ordered indices providing extra operations based on
+ rank, the numerical position of an element
+ in the sequence.
- Hashed indices offer high
efficiency access through hashing techniques.
@@ -379,9 +386,9 @@ Ordered indices
-Revised July 7th 2013
+Revised April 19th 2015
-© Copyright 2003-2013 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/reference/ord_indices.html b/doc/reference/ord_indices.html
index 292ab69..0a1207c 100644
--- a/doc/reference/ord_indices.html
+++ b/doc/reference/ord_indices.html
@@ -21,8 +21,8 @@ Index reference
-
-Hashed indices
+
@@ -1097,15 +1097,15 @@ Index reference
-
-Hashed indices
+
-Revised August 20th 2014
+Revised April 19th 2015
-© Copyright 2003-2014 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/reference/rnk_indices.html b/doc/reference/rnk_indices.html
new file mode 100644
index 0000000..dfd8a71
--- /dev/null
+++ b/doc/reference/rnk_indices.html
@@ -0,0 +1,626 @@
+
+
+
+
+
+Boost.MultiIndex Documentation - Ranked indices reference
+
+
+
+
+
+
+
+
+
Boost.MultiIndex Ranked indices reference
+
+
+
+
+
+
+
+Contents
+
+
+ - Header
+
"boost/multi_index/ranked_index_fwd.hpp"
synopsis
+ - Header
+
"boost/multi_index/ranked_index.hpp"
synopsis
+
+
+
+
+
+Header
+
+"boost/multi_index/ranked_index_fwd.hpp"
synopsis
+
+
+namespace boost{
+
+namespace multi_index{
+
+// index specifiers ranked_unique and ranked_non_unique
+
+template<consult ranked_unique reference for arguments>
+struct ranked_unique;
+template<consult ranked_non_unique reference for arguments>
+struct ranked_non_unique;
+
+// indices
+
+namespace detail{
+
+template<implementation defined> class index name is implementation defined;
+
+} // namespace boost::multi_index::detail
+
+} // namespace boost::multi_index
+
+} // namespace boost
+
+
+
+ranked_index_fwd.hpp
provides forward declarations for index specifiers
+ranked_unique
and ranked_non_unique
and
+their associated ranked index classes.
+
+
+
+Header
+
+"boost/multi_index/ranked_index.hpp"
synopsis
+
+
+#include <initializer_list>
+
+namespace boost{
+
+namespace multi_index{
+
+// index specifiers ranked_unique and ranked_non_unique
+
+template<consult ranked_unique reference for arguments>
+struct ranked_unique;
+template<consult ranked_non_unique reference for arguments>
+struct ranked_non_unique;
+
+// indices
+
+namespace detail{
+
+template<implementation defined> class index class name implementation defined;
+
+// index comparison:
+
+// OP is any of ==,<,!=,>,>=,<=
+
+template<arg set 1,arg set 2>
+bool operator OP(
+ const index class name<arg set 1>& x,const index class name<arg set 2>& y);
+
+// index specialized algorithms:
+
+template<implementation defined>
+void swap(index class name& x,index class name& y);
+
+} // namespace boost::multi_index::detail
+
+} // namespace boost::multi_index
+
+} // namespace boost
+
+
+
+Index specifiers ranked_unique
and ranked_non_unique
+
+
+
+These index specifiers allow
+for insertion of ranked indices without and with
+allowance of duplicate elements, respectively. The syntax of ranked_unique
+and ranked_non_unique
coincide, thus we describe them in a grouped manner.
+ranked_unique
and ranked_non_unique
can be instantiated in
+two different forms, according to whether a tag list for the index is provided or not:
+
+
+
+template<
+ typename KeyFromValue,
+ typename Compare=std::less<KeyFromValue::result_type>
+>
+struct (ranked_unique | ranked_non_unique);
+
+template<
+ typename TagList,
+ typename KeyFromValue,
+ typename Compare=std::less<KeyFromValue::result_type>
+>
+struct (ranked_unique | ranked_non_unique);
+
+
+
+If provided, TagList
must be an instantiation of the class template
+tag
.
+The template arguments are used by the corresponding index implementation,
+refer to the ranked indices reference section for further
+explanations on their acceptable type values.
+
+
+Ranked indices
+
+
+Ranked indices are a variation of ordered indices
+providing additional capabilities for calculation of and access by rank; the rank of an element is the
+distance to it from the beginning of the index. Other than this, ranked indices present
+the same public interface and complexity guarantees than ordered indices, although
+execution times and memory consumption are expected to be poorer due to the internal
+bookkeeping needed to maintain rank-related information.
+As with ordered indices, ranked indices can be unique (no duplicate elements are allowed)
+or non-unique: either version is associated to a different index specifier, but
+the interface of both is the same.
+
+
+
+Being then these a pure extension of ordered indices, we only provide descriptions for
+the extra operations they provide.
+
+
+
+namespace boost{
+
+namespace multi_index{
+
+implementation defined unbounded; // see range_rank()
+
+namespace detail{
+
+template<implementation defined: dependent on types Value, Allocator,
+ TagList, KeyFromValue, Compare>
+class name is implementation defined
+{
+public:
+ // types:
+
+ typedef typename KeyFromValue::result_type key_type;
+ typedef Value value_type;
+ typedef KeyFromValue key_from_value;
+ typedef Compare key_compare;
+ typedef implementation defined value_compare;
+ typedef boost::tuple<key_from_value,key_compare> ctor_args;
+ typedef TagList tag_list;
+ typedef Allocator allocator_type;
+ typedef typename Allocator::reference reference;
+ typedef typename Allocator::const_reference const_reference;
+ typedef implementation defined iterator;
+ typedef implementation defined const_iterator;
+ typedef implementation defined size_type;
+ typedef implementation defined difference_type;
+ typedef typename Allocator::pointer pointer;
+ typedef typename Allocator::const_pointer const_pointer;
+ typedef equivalent to
+ std::reverse_iterator<iterator> reverse_iterator;
+ typedef equivalent to
+ std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // construct/copy/destroy:
+
+ index class name& operator=(const index class name& x);
+ index class name& operator=(std::initializer_list<value_type> list);
+
+ allocator_type get_allocator()const noexcept;
+
+ // iterators:
+
+ iterator begin()noexcept;
+ const_iterator begin()const noexcept;
+ iterator end()noexcept;
+ const_iterator end()const noexcept;
+ reverse_iterator rbegin()noexcept;
+ const_reverse_iterator rbegin()const noexcept;
+ reverse_iterator rend()noexcept;
+ const_reverse_iterator rend()const noexcept;
+ const_iterator cbegin()const noexcept;
+ const_iterator cend()const noexcept;
+ const_reverse_iterator crbegin()const noexcept;
+ const_reverse_iterator crend()const noexcept;
+
+ iterator iterator_to(const value_type& x);
+ const_iterator iterator_to(const value_type& x)const;
+
+ // capacity:
+
+ bool empty()const noexcept;
+ size_type size()const noexcept;
+ size_type max_size()const noexcept;
+
+ // modifiers:
+
+ template<typename... Args>
+ std::pair<iterator,bool> emplace(Args&&... args);
+ template <typename... Args>
+ iterator emplace_hint(iterator position,Args&&... args);
+ std::pair<iterator,bool> insert(const value_type& x);
+ std::pair<iterator,bool> insert(value_type&& x);
+ iterator insert(iterator position,const value_type& x);
+ iterator insert(iterator position,value_type&& x);
+ template<typename InputIterator>
+ void insert(InputIterator first,InputIterator last);
+ void insert(std::initializer_list<value_type> list);
+
+ iterator erase(iterator position);
+ size_type erase(const key_type& x);
+ iterator erase(iterator first,iterator last);
+
+ bool replace(iterator position,const value_type& x);
+ bool replace(iterator position,value_type&& x);
+ template<typename Modifier> bool modify(iterator position,Modifier mod);
+ template<typename Modifier,typename Rollback>
+ bool modify(iterator position,Modifier mod,Rollback back);
+ template<typename Modifier> bool modify_key(iterator position,Modifier mod);
+ template<typename Modifier,typename Rollback>
+ bool modify_key(iterator position,Modifier mod,Rollback back);
+
+ void swap(index class name& x);
+ void clear()noexcept;
+
+ // observers:
+
+ key_from_value key_extractor()const;
+ key_compare key_comp()const;
+ value_compare value_comp()const;
+
+ // set operations:
+
+ template<typename CompatibleKey>
+ iterator find(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ iterator find(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ size_type count(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ iterator lower_bound(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ iterator lower_bound(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ iterator upper_bound(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ iterator upper_bound(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ std::pair<iterator,iterator> equal_range(
+ const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ std::pair<iterator,iterator> equal_range(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ // range:
+
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<iterator,iterator> range(
+ LowerBounder lower,UpperBounder upper)const;
+
+ // rank operations:
+
+ iterator nth(size_type n)const;
+ size_type rank(iterator position)const;
+
+ template<typename CompatibleKey>
+ size_type find_rank(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ size_type find_rank(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ size_type lower_bound_rank(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ size_type lower_bound_rank(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ size_type upper_bound_rank(const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ size_type upper_bound_rank(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename CompatibleKey>
+ std::pair<size_type,size_type> equal_range_rank(
+ const CompatibleKey& x)const;
+ template<typename CompatibleKey,typename CompatibleCompare>
+ std::pair<size_type,size_type> equal_range_rank(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+ template<typename LowerBounder,typename UpperBounder>
+ std::pair<size_type,size_type>
+ range_rank(LowerBounder lower,UpperBounder upper)const;
+};
+
+// index comparison:
+
+template<arg set 1,arg set 2>
+bool operator==(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template<arg set 1,arg set 2>
+bool operator<(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<arg set 1,arg set 2>
+bool operator!=(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return !(x==y);
+}
+
+template<arg set 1,arg set 2>
+bool operator>(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return y<x;
+}
+
+template<arg set 1,arg set 2>
+bool operator>=(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return !(x<y);
+}
+
+template<arg set 1,arg set 2>
+bool operator<=(
+ const index class name<arg set 1>& x,
+ const index class name<arg set 2>& y)
+{
+ return !(x>y);
+}
+
+// index specialized algorithms:
+
+template<implementation defined>
+void swap(index class name& x,index class name& y);
+
+} // namespace boost::multi_index::detail
+
+} // namespace boost::multi_index
+
+} // namespace boost
+
+
+Complexity signature
+
+
+The same as ordered indices.
+
+
+Instantiation types
+
+Ordered indices are instantiated internally to multi_index_container
and
+specified by means of indexed_by
+with index specifiers ranked_unique
+and ranked_non_unique
. Instantiations are dependent on the
+following types:
+
+ Value
from multi_index_container
,
+ Allocator
from multi_index_container
,
+ TagList
from the index specifier (if provided, otherwise tag<>
is assumed),
+ KeyFromValue
from the index specifier,
+ Compare
from the index specifier.
+
+These types are subject to the same requirements as specified for
+ordered indices.
+
+
+Rank operations
+
+
+The rank of an iterator it
of a given container c
(and,
+by extension, of the element it points to if the iterator is dereferenceable)
+is std::distance(c.begin(),it)
.
+
+
+
+See the documentation of ordered indices for an explanation of the notions of
+compatible extension,
+compatible key,
+lower bounder and upper bounder, which are
+referred to above.
+
+
+iterator nth(size_type n)const;
+
+
+Effects: Returns an iterator with rank n
,
+or end()
if n>=size()
.
+Complexity: O(log(n))
.
+
+
+size_type rank(iterator position)const;
+
+
+
+Requires: position
is a valid iterator of the index.
+Effects: Returns the rank of position
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey> size_type find_rank(const CompatibleKey& x)const;
+
+
+
+Requires: CompatibleKey
is a compatible key of
+key_compare
.
+Effects: Equivalent to rank(find(k))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey,typename CompatibleCompare>
+size_type find_rank(const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+
+
+Requires: (CompatibleKey
, CompatibleCompare
)
+is a compatible extension of key_compare
.
+Effects: Equivalent to rank(find(x,comp))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey>
+size_type lower_bound_rank(const CompatibleKey& x)const;
+
+
+
+Requires: CompatibleKey
is a compatible key of
+key_compare
.
+Effects: Equivalent to rank(lower_bound(x))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey,typename CompatibleCompare>
+size_type lower_bound_rank(const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+
+
+Requires: (CompatibleKey
, CompatibleCompare
)
+is a compatible extension of key_compare
.
+Effects: Equivalent to rank(lower_bound(x,comp))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey>
+size_type upper_bound_rank(const CompatibleKey& x)const;
+
+
+
+Requires: CompatibleKey
is a compatible key of
+key_compare
.
+Effects: Equivalent to rank(upper_bound(x))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey,typename CompatibleCompare>
+size_type upper_bound_rank(const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+
+
+Requires: (CompatibleKey
, CompatibleCompare
)
+is a compatible extension of key_compare
.
+Effects: Equivalent to rank(upper_bound(x,comp))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey>
+std::pair<size_type,size_type> equal_range_rank(
+ const CompatibleKey& x)const;
+
+
+
+Requires: CompatibleKey
is a compatible key of
+key_compare
.
+Effects: Equivalent to make_pair(lower_bound_rank(x),upper_bound_rank(x))
.
+Complexity: O(log(n))
.
+
+
+template<typename CompatibleKey,typename CompatibleCompare>
+std::pair<size_type,size_type> equal_range_rank(
+ const CompatibleKey& x,const CompatibleCompare& comp)const;
+
+
+
+Requires: (CompatibleKey
, CompatibleCompare
)
+is a compatible extension of key_compare
.
+Effects: Equivalent to
+make_pair(lower_bound_rank(x,comp),upper_bound_rank(x,comp))
.
+Complexity: O(log(n))
.
+
+
+template<typename LowerBounder,typename UpperBounder>
+std::pair<size_type,size_type> range_rank(
+ LowerBounder lower,UpperBounder upper)const;
+
+
+
+Requires: LowerBounder
and UpperBounder
are
+a lower and upper bounder of key_compare
, respectively.
+Effects: Equivalent to
+
+auto p=range(lower,upper);
+return make_pair(rank(p.first),rank(p.second));
+
+Complexity: O(log(n))
.
+Variants: In place of lower
or upper
(or both),
+the singular value boost::multi_index::unbounded
can be
+provided. This acts as a predicate which all values of type key_type
+satisfy.
+
+
+Serialization
+
+
+The prerequisites and postconditions associated to serialization of
+multi_index_container
s with ranked indices are exactly the same
+as those of ordered indices.
+
+
+
+
+
+
+
+
+
+Revised April 19th 2015
+
+© Copyright 2003-2015 Joaquín M López Muñoz.
+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/doc/release_notes.html b/doc/release_notes.html
index f1da028..529b32d 100644
--- a/doc/release_notes.html
+++ b/doc/release_notes.html
@@ -56,6 +56,7 @@ Acknowledgements
+ - Added ranked indices.
- Maintenance fixes.
@@ -500,7 +501,7 @@ Acknowledgements
-Revised March 25th 2015
+Revised April 19th 2015
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
diff --git a/doc/tests.html b/doc/tests.html
index 1d7131c..1adc0f5 100644
--- a/doc/tests.html
+++ b/doc/tests.html
@@ -107,28 +107,32 @@ with some of the least common features offered by Boost.MultiIndex.
Exercises the range
facility (ordered indices only).
+ test_rank_ops.cpp
+ Specific operations of ranked indices.
+
+
test_rearrange.cpp
Rearrange functions of sequenced and random access indices.
-
+
test_safe_mode.cpp
Comprehensive coverage of all conditions checked in safe mode.
-
+
test_serialization1.cpp
test_serialization2.cpp
test_serialization3.cpp
Serialization support.
-
+
test_set_ops.cpp
Set-like operations particular to ordered indices.
-
+
test_special_set_ops.cpp
Checks special lookup operations using compatible sorting criteria.
-
+
test_update.cpp
replace
, modify
and modify_key
.
@@ -150,9 +154,9 @@ Future work
-Revised July 11th 2007
+Revised April 19th 2015
-© Copyright 2003-2007 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/tutorial/basics.html b/doc/tutorial/basics.html
index 14ed98f..9ca3f0a 100644
--- a/doc/tutorial/basics.html
+++ b/doc/tutorial/basics.html
@@ -497,6 +497,10 @@ Currently, Boost.MultiIndex provides the following index types:
provide a similar interface. There are unique and non-unique
variants: the former do not allow for duplicates, while the latter permit
them (like std::multiset
.)
+ Ranked indices are a variation of ordered indices providing extra capabilities
+ for querying and accessing elements based on their rank (the numerical position
+ they occupy in the index).
+
Sequenced indices are modeled after the semantics and interface of
std::list
: they arrange the elements as if in a bidirectional
list.
@@ -1248,9 +1252,9 @@ Index types
-Revised November 11th 2014
+Revised April 19th 2015
-© Copyright 2003-2014 Joaquín M López Muñoz.
+
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at
diff --git a/doc/tutorial/indices.html b/doc/tutorial/indices.html
index dd3739a..b0b95f1 100644
--- a/doc/tutorial/indices.html
+++ b/doc/tutorial/indices.html
@@ -31,6 +31,12 @@ Key extraction
- Classification
+
- Ranked indices
+
+ - Specification
+ - Rank operations
+
+
- Hashed indices
- Unique and non-unique variants
@@ -71,13 +77,19 @@ some added benefits, functionally or in the area of performance.
specifier
- key-based
- ordered
+ key-based
+ ordered
ordered_unique
ordered_non_unique
+
+ ranked_unique
+
+
+ ranked_non_unique
+
hashed
hashed_unique
@@ -108,6 +120,111 @@ modeled after the interface of std::list
, are the customary
example of a non key-based index.
+Ranked indices
+
+
+Suppose we have a std::multiset
of numbers and we want to output
+the values above the 75h percentile:
+
+
+
+typedef std::multiset<int> int_multiset;
+
+void output_above_75th_percentile(const int_multiset& s)
+{
+ int_multiset::const_iterator it=s.begin();
+ std::advance(it,s.size()*3/4); // linear on s.size();
+
+ std::copy(it,s.end(),std::ostream_iterator<int>(std::cout,"\n"));
+}
+
+
+
+The problem with this code is that getting to the beginning of the desired subsequence
+involves a linear traversal of the container. Ranked indices provide the mechanisms to do this
+much faster:
+
+
+
+typedef multi_index_container<
+ int,
+ indexed_by<
+ ranked_non_unique<identity<int> >
+ >
+> int_multiset;
+
+void output_above_75th_percentile(const int_multiset& s)
+{
+ int_multiset::const_iterator it=s.nth(s.size()*3/4); // logarithmic
+ std::copy(it,s.end(),std::ostream_iterator<int>(std::cout,"\n"));
+}
+
+
+
+nth(n)
returns an iterator to the element whose rank, i.e. its distance
+from the beginning of the index, is n
, and does so efficiently in logarithmic time.
+Conversely, rank(it)
computes in logarithmic time the rank of the element
+pointed to by it
, or size()
if it==end()
.
+
+
+
+int_multiset::iterator it=s.insert(10).first;
+int_multiset::size_type r=s.rank(it); // rank of 10;
+
+
+
+Ranked indices provide the same interface as ordered indices plus several rank-related operations.
+The cost of this extra functionality is higher memory consumption due to some internal additional
+data (one word per element) and marginally longer execution times in insertion and erasure.
+The reference describes these indices in complete detail.
+
+
+Specification
+
+
+The specification of ranked indices is done exactly as with ordered indices,
+except that ranked_unique
and ranked_non_unique
are used instead.
+
+
+
+(ranked_unique | ranked_non_unique)
+ <[(tag)[,(key extractor)[,(comparison predicate)]]]>
+
+(ranked_unique | ranked_non_unique)
+ <[(key extractor)[,(comparison predicate)]]>
+
+
+Rank operations
+
+
+Besides nth
and rank
, ranked indices provide member functions
+
+ find_rank
,
+ lower_bound_rank
,
+ upper_bound_rank
,
+ equal_range_rank
and
+ range_rank
+
+that behave as their normal
+lookup and range retrieval
+counterparts (find
, lower_bound
etc.) but return ranks rather than iterators.
+
+
+
+void percentile(int n,const int_multiset& s)
+{
+ std::cout<<n<<" lies in the "<<
+ s.upper_bound_rank(n)*100.0/s.size()<<" percentile\n";
+}
+
+
+
+You might think that upper_bound_rank(n)
is mere shorthand for
+rank(upper_bound(n))
: in reality, though, you should prefer using
+*_rank
operations directly as they run faster than the
+alternative formulations.
+
+
Hashed indices
@@ -162,25 +279,10 @@ determining whether a hashed index is preferred over an ordered one.
-If you are familiar with non-standard hash_set
s provided
-by some compiler vendors, then learning to use hashed indices should be straightforward.
-However, the interface of hashed indices is modeled after the specification
-for unordered associative containers by the
-C++ Standard
-Library Technical Report (TR1),
-which differs in some significant aspects from existing pre-standard
-implementations:
-
- - As there is no notion of ordering between keys, the lookup
- interface does not offer
lower_bound
or upper_bound
- member functions (unlike Dinkumware's solution.)
- - A set of member functions is provided for handling the internal
- bucket structure on which hashed indices rely. This includes facilities
- for rehashing,
- control of the load factor (number of elements divided by number of buckets),
- and inspection of the buckets contents. Pre-standard implementations
- do not have such an extensive functionality.
-
+Hashed indices replicate the interface as std::unordered_set
and
+std::unordered_multiset
, with only minor differences where required
+by the general constraints of multi_index_container
s, and provide
+additional useful capabilities like in-place updating of elements.
Check the reference for a
complete specification of the interface of hashed indices,
and example 8 and
@@ -352,19 +454,18 @@ member functions, with the same functionality as in ordered indices.
Due to the internal constraints imposed by the Boost.MultiIndex framework,
hashed indices provide guarantees on iterator validity and
exception safety that are actually stronger than required by the
-C++ Standard Library Technical Report (TR1) with respect
-to unordered associative containers:
+C++ standard with respect to unordered associative containers:
- Iterator validity is preserved in any case during insertion or rehashing:
- TR1 allows for iterator invalidation when a rehash (implicit or explicit)
+ C++ unordered associative containers can invalidate iterators when a rehash (implicit or explicit)
is performed.
- Erasing an element or range of elements via iterators does not throw ever,
as the internal hash function and equality predicate objects are not actually
invoked.
rehash
provides the strong exception safety guarantee
- unconditionally. TR1 only warrants it if the internal hash function and
+ unconditionally. The standard only warrants it for unordered associative containers if the internal hash function and
equality predicate objects do not throw. The somewhat surprising consequence
- is that a TR1-compliant unordered associative container might erase
+ is that a standard-compliant std::unordered_set
might erase
elements if an exception is thrown during rehashing!
In general, these stronger guarantees play in favor of the user's convenience,
@@ -673,7 +774,7 @@ in scenarios where access via iterators is not suitable or desireable:
Ordered indices node compression
-Ordered indices are implemented by means of a data structure
+Ordered and ranked indices are implemented by means of a data structure
known as a red-black tree. Nodes of a red-back tree contain pointers
to the parent and the two children nodes, plus a 1-bit field referred to as
the node color (hence the name of the structure). Due to alignment
@@ -687,7 +788,7 @@ significant bit of the address must always be zero.
-Boost.MultiIndex ordered indices implement this type of node compression
+Boost.MultiIndex ordered and ranked indices implement this type of node compression
whenever applicable. As compared with common implementations of the STL
container std::set
, node compression can
result in a reduction of header overload by 25% (from 16 to 12 bytes on
@@ -717,7 +818,7 @@ Key extraction
-
Revised March 25th 2015
+Revised April 19th 2015
© Copyright 2003-2015 Joaquín M López Muñoz.
Distributed under the Boost Software
diff --git a/include/boost/multi_index/detail/ord_index_impl.hpp b/include/boost/multi_index/detail/ord_index_impl.hpp
new file mode 100644
index 0000000..6debf07
--- /dev/null
+++ b/include/boost/multi_index/detail/ord_index_impl.hpp
@@ -0,0 +1,1564 @@
+/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+ * 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/multi_index for library home page.
+ *
+ * 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.
+ *
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include /* keep it first to prevent nasty warns in MSVC */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include
+#endif
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+#include
+#include
+#include
+#include
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x) \
+ detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
+ detail::make_obj_guard(x,&ordered_index_impl::check_invariant_); \
+ BOOST_JOIN(check_invariant_,__LINE__).touch();
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT \
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(*this)
+#else
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x)
+#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* ordered_index adds a layer of ordered indexing to a given Super and accepts
+ * an augmenting policy for optional addition of order statistics.
+ */
+
+/* Most of the implementation of unique and non-unique indices is
+ * shared. We tell from one another on instantiation time by using
+ * these tags.
+ */
+
+struct ordered_unique_tag{};
+struct ordered_non_unique_tag{};
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+class ordered_index;
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+class ordered_index_impl:
+ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ ,public safe_mode::safe_container<
+ ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy> >
+#endif
+
+{
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+ BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
+ * lifetime of const references bound to temporaries --precisely what
+ * scopeguards are.
+ */
+
+#pragma parse_mfunc_templ off
+#endif
+
+ typedef typename SuperMeta::type super;
+
+protected:
+ typedef ordered_index_node<
+ AugmentPolicy,typename super::node_type> node_type;
+
+protected: /* for the benefit of AugmentPolicy::augmented_interface */
+ typedef typename node_type::impl_type node_impl_type;
+ typedef typename node_impl_type::pointer node_impl_pointer;
+
+public:
+ /* types */
+
+ typedef typename KeyFromValue::result_type key_type;
+ typedef typename node_type::value_type value_type;
+ typedef KeyFromValue key_from_value;
+ typedef Compare key_compare;
+ typedef value_comparison<
+ value_type,KeyFromValue,Compare> value_compare;
+ typedef tuple ctor_args;
+ typedef typename super::final_allocator_type allocator_type;
+ typedef typename allocator_type::reference reference;
+ typedef typename allocator_type::const_reference const_reference;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ typedef safe_mode::safe_iterator<
+ bidir_node_iterator,
+ ordered_index_impl> iterator;
+#else
+ typedef bidir_node_iterator iterator;
+#endif
+
+ typedef iterator const_iterator;
+
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef typename allocator_type::pointer pointer;
+ typedef typename allocator_type::const_pointer const_pointer;
+ typedef typename
+ boost::reverse_iterator reverse_iterator;
+ typedef typename
+ boost::reverse_iterator const_reverse_iterator;
+ typedef TagList tag_list;
+
+protected:
+ typedef typename super::final_node_type final_node_type;
+ typedef tuples::cons<
+ ctor_args,
+ typename super::ctor_args_list> ctor_args_list;
+ typedef typename mpl::push_front<
+ typename super::index_type_list,
+ ordered_index<
+ KeyFromValue,Compare,
+ SuperMeta,TagList,Category,AugmentPolicy
+ > >::type index_type_list;
+ typedef typename mpl::push_front<
+ typename super::iterator_type_list,
+ iterator>::type iterator_type_list;
+ typedef typename mpl::push_front<
+ typename super::const_iterator_type_list,
+ const_iterator>::type const_iterator_type_list;
+ typedef typename super::copy_map_type copy_map_type;
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+ typedef typename super::index_saver_type index_saver_type;
+ typedef typename super::index_loader_type index_loader_type;
+#endif
+
+protected:
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ typedef safe_mode::safe_container<
+ ordered_index_impl> safe_super;
+#endif
+
+ typedef typename call_traits<
+ value_type>::param_type value_param_type;
+ typedef typename call_traits<
+ key_type>::param_type key_param_type;
+
+ /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
+ * expansion.
+ */
+
+ typedef std::pair emplace_return_type;
+
+public:
+
+ /* construct/copy/destroy
+ * Default and copy ctors are in the protected section as indices are
+ * not supposed to be created on their own. No range ctor either.
+ * Assignment operator defined at ordered_index rather than here.
+ */
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ ordered_index&
+ operator=(std::initializer_list list)
+ {
+ this->final()=list;
+ return *static_cast<
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>*>(this);
+ }
+#endif
+
+ allocator_type get_allocator()const BOOST_NOEXCEPT
+ {
+ return this->final().get_allocator();
+ }
+
+ /* iterators */
+
+ iterator
+ begin()BOOST_NOEXCEPT{return make_iterator(leftmost());}
+ const_iterator
+ begin()const BOOST_NOEXCEPT{return make_iterator(leftmost());}
+ iterator
+ end()BOOST_NOEXCEPT{return make_iterator(header());}
+ const_iterator
+ end()const BOOST_NOEXCEPT{return make_iterator(header());}
+ reverse_iterator
+ rbegin()BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
+ const_reverse_iterator
+ rbegin()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(end());}
+ reverse_iterator
+ rend()BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
+ const_reverse_iterator
+ rend()const BOOST_NOEXCEPT{return boost::make_reverse_iterator(begin());}
+ const_iterator
+ cbegin()const BOOST_NOEXCEPT{return begin();}
+ const_iterator
+ cend()const BOOST_NOEXCEPT{return end();}
+ const_reverse_iterator
+ crbegin()const BOOST_NOEXCEPT{return rbegin();}
+ const_reverse_iterator
+ crend()const BOOST_NOEXCEPT{return rend();}
+
+ iterator iterator_to(const value_type& x)
+ {
+ return make_iterator(node_from_value(&x));
+ }
+
+ const_iterator iterator_to(const value_type& x)const
+ {
+ return make_iterator(node_from_value(&x));
+ }
+
+ /* capacity */
+
+ bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
+ size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
+ size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
+
+ /* modifiers */
+
+ BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
+ emplace_return_type,emplace,emplace_impl)
+
+ BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
+ iterator,emplace_hint,emplace_hint_impl,iterator,position)
+
+ std::pair insert(const value_type& x)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pair p=this->final_insert_(x);
+ return std::pair(make_iterator(p.first),p.second);
+ }
+
+ std::pair insert(BOOST_RV_REF(value_type) x)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pair p=this->final_insert_rv_(x);
+ return std::pair(make_iterator(p.first),p.second);
+ }
+
+ iterator insert(iterator position,const value_type& x)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pair p=this->final_insert_(
+ x,static_cast(position.get_node()));
+ return make_iterator(p.first);
+ }
+
+ iterator insert(iterator position,BOOST_RV_REF(value_type) x)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pair p=this->final_insert_rv_(
+ x,static_cast(position.get_node()));
+ return make_iterator(p.first);
+ }
+
+ template
+ void insert(InputIterator first,InputIterator last)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ node_type* hint=header(); /* end() */
+ for(;first!=last;++first){
+ hint=this->final_insert_ref_(
+ *first,static_cast(hint)).first;
+ node_type::increment(hint);
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ void insert(std::initializer_list list)
+ {
+ insert(list.begin(),list.end());
+ }
+#endif
+
+ iterator erase(iterator position)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ this->final_erase_(static_cast(position++.get_node()));
+ return position;
+ }
+
+ size_type erase(key_param_type x)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pair p=equal_range(x);
+ size_type s=0;
+ while(p.first!=p.second){
+ p.first=erase(p.first);
+ ++s;
+ }
+ return s;
+ }
+
+ iterator erase(iterator first,iterator last)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
+ BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ while(first!=last){
+ first=erase(first);
+ }
+ return first;
+ }
+
+ bool replace(iterator position,const value_type& x)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ return this->final_replace_(
+ x,static_cast(position.get_node()));
+ }
+
+ bool replace(iterator position,BOOST_RV_REF(value_type) x)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ return this->final_replace_rv_(
+ x,static_cast(position.get_node()));
+ }
+
+ template
+ bool modify(iterator position,Modifier mod)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,static_cast(position.get_node()));
+ }
+
+ template
+ bool modify(iterator position,Modifier mod,Rollback back_)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ /* MSVC++ 6.0 optimizer on safe mode code chokes if this
+ * this is not added. Left it for all compilers as it does no
+ * harm.
+ */
+
+ position.detach();
+#endif
+
+ return this->final_modify_(
+ mod,back_,static_cast(position.get_node()));
+ }
+
+ template
+ bool modify_key(iterator position,Modifier mod)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ return modify(
+ position,modify_key_adaptor(mod,key));
+ }
+
+ template
+ bool modify_key(iterator position,Modifier mod,Rollback back_)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ return modify(
+ position,
+ modify_key_adaptor(mod,key),
+ modify_key_adaptor(back_,key));
+ }
+
+ void swap(
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x);
+ this->final_swap_(x.final());
+ }
+
+ void clear()BOOST_NOEXCEPT
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ this->final_clear_();
+ }
+
+ /* observers */
+
+ key_from_value key_extractor()const{return key;}
+ key_compare key_comp()const{return comp_;}
+ value_compare value_comp()const{return value_compare(key,comp_);}
+
+ /* set operations */
+
+ /* Internally, these ops rely on const_iterator being the same
+ * type as iterator.
+ */
+
+ template
+ iterator find(const CompatibleKey& x)const
+ {
+ return make_iterator(ordered_index_find(root(),header(),key,x,comp_));
+ }
+
+ template
+ iterator find(
+ const CompatibleKey& x,const CompatibleCompare& comp)const
+ {
+ return make_iterator(ordered_index_find(root(),header(),key,x,comp));
+ }
+
+ template
+ size_type count(const CompatibleKey& x)const
+ {
+ return count(x,comp_);
+ }
+
+ template
+ size_type count(const CompatibleKey& x,const CompatibleCompare& comp)const
+ {
+ std::pair p=equal_range(x,comp);
+ size_type n=std::distance(p.first,p.second);
+ return n;
+ }
+
+ template
+ iterator lower_bound(const CompatibleKey& x)const
+ {
+ return make_iterator(
+ ordered_index_lower_bound(root(),header(),key,x,comp_));
+ }
+
+ template
+ iterator lower_bound(
+ const CompatibleKey& x,const CompatibleCompare& comp)const
+ {
+ return make_iterator(
+ ordered_index_lower_bound(root(),header(),key,x,comp));
+ }
+
+ template
+ iterator upper_bound(const CompatibleKey& x)const
+ {
+ return make_iterator(
+ ordered_index_upper_bound(root(),header(),key,x,comp_));
+ }
+
+ template
+ iterator upper_bound(
+ const CompatibleKey& x,const CompatibleCompare& comp)const
+ {
+ return make_iterator(
+ ordered_index_upper_bound(root(),header(),key,x,comp));
+ }
+
+ template
+ std::pair equal_range(
+ const CompatibleKey& x)const
+ {
+ std::pair p=
+ ordered_index_equal_range(root(),header(),key,x,comp_);
+ return std::pair(
+ make_iterator(p.first),make_iterator(p.second));
+ }
+
+ template
+ std::pair equal_range(
+ const CompatibleKey& x,const CompatibleCompare& comp)const
+ {
+ std::pair p=
+ ordered_index_equal_range(root(),header(),key,x,comp);
+ return std::pair(
+ make_iterator(p.first),make_iterator(p.second));
+ }
+
+ /* range */
+
+ template
+ std::pair
+ range(LowerBounder lower,UpperBounder upper)const
+ {
+ typedef typename mpl::if_<
+ is_same,
+ BOOST_DEDUCED_TYPENAME mpl::if_<
+ is_same,
+ both_unbounded_tag,
+ lower_unbounded_tag
+ >::type,
+ BOOST_DEDUCED_TYPENAME mpl::if_<
+ is_same,
+ upper_unbounded_tag,
+ none_unbounded_tag
+ >::type
+ >::type dispatch;
+
+ return range(lower,upper,dispatch());
+ }
+
+BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
+ ordered_index_impl(const ctor_args_list& args_list,const allocator_type& al):
+ super(args_list.get_tail(),al),
+ key(tuples::get<0>(args_list.get_head())),
+ comp_(tuples::get<1>(args_list.get_head()))
+ {
+ empty_initialize();
+ }
+
+ ordered_index_impl(
+ const ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x):
+ super(x),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ safe_super(),
+#endif
+
+ key(x.key),
+ comp_(x.comp_)
+ {
+ /* Copy ctor just takes the key and compare objects from x. The rest is
+ * done in a subsequent call to copy_().
+ */
+ }
+
+ ordered_index_impl(
+ const ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
+ do_not_copy_elements_tag):
+ super(x,do_not_copy_elements_tag()),
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ safe_super(),
+#endif
+
+ key(x.key),
+ comp_(x.comp_)
+ {
+ empty_initialize();
+ }
+
+ ~ordered_index_impl()
+ {
+ /* the container is guaranteed to be empty by now */
+ }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ iterator make_iterator(node_type* node){return iterator(node,this);}
+ const_iterator make_iterator(node_type* node)const
+ {return const_iterator(node,const_cast(this));}
+#else
+ iterator make_iterator(node_type* node){return iterator(node);}
+ const_iterator make_iterator(node_type* node)const
+ {return const_iterator(node);}
+#endif
+
+ void copy_(
+ const ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
+ const copy_map_type& map)
+ {
+ if(!x.root()){
+ empty_initialize();
+ }
+ else{
+ header()->color()=x.header()->color();
+ AugmentPolicy::copy(x.header()->impl(),header()->impl());
+
+ node_type* root_cpy=map.find(static_cast(x.root()));
+ header()->parent()=root_cpy->impl();
+
+ node_type* leftmost_cpy=map.find(
+ static_cast(x.leftmost()));
+ header()->left()=leftmost_cpy->impl();
+
+ node_type* rightmost_cpy=map.find(
+ static_cast(x.rightmost()));
+ header()->right()=rightmost_cpy->impl();
+
+ typedef typename copy_map_type::const_iterator copy_map_iterator;
+ for(copy_map_iterator it=map.begin(),it_end=map.end();it!=it_end;++it){
+ node_type* org=it->first;
+ node_type* cpy=it->second;
+
+ cpy->color()=org->color();
+ AugmentPolicy::copy(org->impl(),cpy->impl());
+
+ node_impl_pointer parent_org=org->parent();
+ if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
+ else{
+ node_type* parent_cpy=map.find(
+ static_cast(node_type::from_impl(parent_org)));
+ cpy->parent()=parent_cpy->impl();
+ if(parent_org->left()==org->impl()){
+ parent_cpy->left()=cpy->impl();
+ }
+ else if(parent_org->right()==org->impl()){
+ /* header() does not satisfy this nor the previous check */
+ parent_cpy->right()=cpy->impl();
+ }
+ }
+
+ if(org->left()==node_impl_pointer(0))
+ cpy->left()=node_impl_pointer(0);
+ if(org->right()==node_impl_pointer(0))
+ cpy->right()=node_impl_pointer(0);
+ }
+ }
+
+ super::copy_(x,map);
+ }
+
+ template
+ final_node_type* insert_(
+ value_param_type v,final_node_type*& x,Variant variant)
+ {
+ link_info inf;
+ if(!link_point(key(v),inf,Category())){
+ return static_cast(node_type::from_impl(inf.pos));
+ }
+
+ final_node_type* res=super::insert_(v,x,variant);
+ if(res==x){
+ node_impl_type::link(
+ static_cast(x)->impl(),inf.side,inf.pos,header()->impl());
+ }
+ return res;
+ }
+
+ template
+ final_node_type* insert_(
+ value_param_type v,node_type* position,final_node_type*& x,Variant variant)
+ {
+ link_info inf;
+ if(!hinted_link_point(key(v),position,inf,Category())){
+ return static_cast(node_type::from_impl(inf.pos));
+ }
+
+ final_node_type* res=super::insert_(v,position,x,variant);
+ if(res==x){
+ node_impl_type::link(
+ static_cast(x)->impl(),inf.side,inf.pos,header()->impl());
+ }
+ return res;
+ }
+
+ void erase_(node_type* x)
+ {
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+ super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ detach_iterators(x);
+#endif
+ }
+
+ void delete_all_nodes_()
+ {
+ delete_all_nodes(root());
+ }
+
+ void clear_()
+ {
+ super::clear_();
+ empty_initialize();
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ safe_super::detach_dereferenceable_iterators();
+#endif
+ }
+
+ void swap_(
+ ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
+ {
+ std::swap(key,x.key);
+ std::swap(comp_,x.comp_);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ safe_super::swap(x);
+#endif
+
+ super::swap_(x);
+ }
+
+ void swap_elements_(
+ ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
+ {
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ safe_super::swap(x);
+#endif
+
+ super::swap_elements_(x);
+ }
+
+ template
+ bool replace_(value_param_type v,node_type* x,Variant variant)
+ {
+ if(in_place(v,x,Category())){
+ return super::replace_(v,x,variant);
+ }
+
+ node_type* next=x;
+ node_type::increment(next);
+
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+
+ BOOST_TRY{
+ link_info inf;
+ if(link_point(key(v),inf,Category())&&super::replace_(v,x,variant)){
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+ return true;
+ }
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ return false;
+ }
+ BOOST_CATCH(...){
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
+ bool modify_(node_type* x)
+ {
+ bool b;
+ BOOST_TRY{
+ b=in_place(x->value(),x,Category());
+ }
+ BOOST_CATCH(...){
+ erase_(x);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ if(!b){
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+ BOOST_TRY{
+ link_info inf;
+ if(!link_point(key(x->value()),inf,Category())){
+ super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ detach_iterators(x);
+#endif
+ return false;
+ }
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+ }
+ BOOST_CATCH(...){
+ super::erase_(x);
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ detach_iterators(x);
+#endif
+
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
+ BOOST_TRY{
+ if(!super::modify_(x)){
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ detach_iterators(x);
+#endif
+
+ return false;
+ }
+ else return true;
+ }
+ BOOST_CATCH(...){
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ detach_iterators(x);
+#endif
+
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
+ bool modify_rollback_(node_type* x)
+ {
+ if(in_place(x->value(),x,Category())){
+ return super::modify_rollback_(x);
+ }
+
+ node_type* next=x;
+ node_type::increment(next);
+
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+
+ BOOST_TRY{
+ link_info inf;
+ if(link_point(key(x->value()),inf,Category())&&
+ super::modify_rollback_(x)){
+ node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
+ return true;
+ }
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ return false;
+ }
+ BOOST_CATCH(...){
+ node_impl_type::restore(x->impl(),next->impl(),header()->impl());
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+ /* serialization */
+
+ template
+ void save_(
+ Archive& ar,const unsigned int version,const index_saver_type& sm)const
+ {
+ save_(ar,version,sm,Category());
+ }
+
+ template
+ void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
+ {
+ load_(ar,version,lm,Category());
+ }
+#endif
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
+ /* invariant stuff */
+
+ bool invariant_()const
+ {
+ if(size()==0||begin()==end()){
+ if(size()!=0||begin()!=end()||
+ header()->left()!=header()->impl()||
+ header()->right()!=header()->impl())return false;
+ }
+ else{
+ if((size_type)std::distance(begin(),end())!=size())return false;
+
+ std::size_t len=node_impl_type::black_count(
+ leftmost()->impl(),root()->impl());
+ for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
+ node_type* x=it.get_node();
+ node_type* left_x=node_type::from_impl(x->left());
+ node_type* right_x=node_type::from_impl(x->right());
+
+ if(x->color()==red){
+ if((left_x&&left_x->color()==red)||
+ (right_x&&right_x->color()==red))return false;
+ }
+ if(left_x&&comp_(key(x->value()),key(left_x->value())))return false;
+ if(right_x&&comp_(key(right_x->value()),key(x->value())))return false;
+ if(!left_x&&!right_x&&
+ node_impl_type::black_count(x->impl(),root()->impl())!=len)
+ return false;
+ if(!AugmentPolicy::invariant(x->impl()))return false;
+ }
+
+ if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
+ return false;
+ if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
+ return false;
+ }
+
+ return super::invariant_();
+ }
+
+
+ /* This forwarding function eases things for the boost::mem_fn construct
+ * in BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT. Actually,
+ * final_check_invariant is already an inherited member function of
+ * ordered_index_impl.
+ */
+ void check_invariant_()const{this->final_check_invariant_();}
+#endif
+
+protected: /* for the benefit of AugmentPolicy::augmented_interface */
+ node_type* header()const{return this->final_header();}
+ node_type* root()const{return node_type::from_impl(header()->parent());}
+ node_type* leftmost()const{return node_type::from_impl(header()->left());}
+ node_type* rightmost()const{return node_type::from_impl(header()->right());}
+
+private:
+ void empty_initialize()
+ {
+ header()->color()=red;
+ /* used to distinguish header() from root, in iterator.operator++ */
+
+ header()->parent()=node_impl_pointer(0);
+ header()->left()=header()->impl();
+ header()->right()=header()->impl();
+ }
+
+ struct link_info
+ {
+ /* coverity[uninit_ctor]: suppress warning */
+ link_info():side(to_left){}
+
+ ordered_index_side side;
+ node_impl_pointer pos;
+ };
+
+ bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
+ {
+ node_type* y=header();
+ node_type* x=root();
+ bool c=true;
+ while(x){
+ y=x;
+ c=comp_(k,key(x->value()));
+ x=node_type::from_impl(c?x->left():x->right());
+ }
+ node_type* yy=y;
+ if(c){
+ if(yy==leftmost()){
+ inf.side=to_left;
+ inf.pos=y->impl();
+ return true;
+ }
+ else node_type::decrement(yy);
+ }
+
+ if(comp_(key(yy->value()),k)){
+ inf.side=c?to_left:to_right;
+ inf.pos=y->impl();
+ return true;
+ }
+ else{
+ inf.pos=yy->impl();
+ return false;
+ }
+ }
+
+ bool link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
+ {
+ node_type* y=header();
+ node_type* x=root();
+ bool c=true;
+ while (x){
+ y=x;
+ c=comp_(k,key(x->value()));
+ x=node_type::from_impl(c?x->left():x->right());
+ }
+ inf.side=c?to_left:to_right;
+ inf.pos=y->impl();
+ return true;
+ }
+
+ bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
+ {
+ node_type* y=header();
+ node_type* x=root();
+ bool c=false;
+ while (x){
+ y=x;
+ c=comp_(key(x->value()),k);
+ x=node_type::from_impl(c?x->right():x->left());
+ }
+ inf.side=c?to_right:to_left;
+ inf.pos=y->impl();
+ return true;
+ }
+
+ bool hinted_link_point(
+ key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
+ {
+ if(position->impl()==header()->left()){
+ if(size()>0&&comp_(k,key(position->value()))){
+ inf.side=to_left;
+ inf.pos=position->impl();
+ return true;
+ }
+ else return link_point(k,inf,ordered_unique_tag());
+ }
+ else if(position==header()){
+ if(comp_(key(rightmost()->value()),k)){
+ inf.side=to_right;
+ inf.pos=rightmost()->impl();
+ return true;
+ }
+ else return link_point(k,inf,ordered_unique_tag());
+ }
+ else{
+ node_type* before=position;
+ node_type::decrement(before);
+ if(comp_(key(before->value()),k)&&comp_(k,key(position->value()))){
+ if(before->right()==node_impl_pointer(0)){
+ inf.side=to_right;
+ inf.pos=before->impl();
+ return true;
+ }
+ else{
+ inf.side=to_left;
+ inf.pos=position->impl();
+ return true;
+ }
+ }
+ else return link_point(k,inf,ordered_unique_tag());
+ }
+ }
+
+ bool hinted_link_point(
+ key_param_type k,node_type* position,link_info& inf,ordered_non_unique_tag)
+ {
+ if(position->impl()==header()->left()){
+ if(size()>0&&!comp_(key(position->value()),k)){
+ inf.side=to_left;
+ inf.pos=position->impl();
+ return true;
+ }
+ else return lower_link_point(k,inf,ordered_non_unique_tag());
+ }
+ else if(position==header()){
+ if(!comp_(k,key(rightmost()->value()))){
+ inf.side=to_right;
+ inf.pos=rightmost()->impl();
+ return true;
+ }
+ else return link_point(k,inf,ordered_non_unique_tag());
+ }
+ else{
+ node_type* before=position;
+ node_type::decrement(before);
+ if(!comp_(k,key(before->value()))){
+ if(!comp_(key(position->value()),k)){
+ if(before->right()==node_impl_pointer(0)){
+ inf.side=to_right;
+ inf.pos=before->impl();
+ return true;
+ }
+ else{
+ inf.side=to_left;
+ inf.pos=position->impl();
+ return true;
+ }
+ }
+ else return lower_link_point(k,inf,ordered_non_unique_tag());
+ }
+ else return link_point(k,inf,ordered_non_unique_tag());
+ }
+ }
+
+ void delete_all_nodes(node_type* x)
+ {
+ if(!x)return;
+
+ delete_all_nodes(node_type::from_impl(x->left()));
+ delete_all_nodes(node_type::from_impl(x->right()));
+ this->final_delete_node_(static_cast(x));
+ }
+
+ bool in_place(value_param_type v,node_type* x,ordered_unique_tag)
+ {
+ node_type* y;
+ if(x!=leftmost()){
+ y=x;
+ node_type::decrement(y);
+ if(!comp_(key(y->value()),key(v)))return false;
+ }
+
+ y=x;
+ node_type::increment(y);
+ return y==header()||comp_(key(v),key(y->value()));
+ }
+
+ bool in_place(value_param_type v,node_type* x,ordered_non_unique_tag)
+ {
+ node_type* y;
+ if(x!=leftmost()){
+ y=x;
+ node_type::decrement(y);
+ if(comp_(key(v),key(y->value())))return false;
+ }
+
+ y=x;
+ node_type::increment(y);
+ return y==header()||!comp_(key(y->value()),key(v));
+ }
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
+ void detach_iterators(node_type* x)
+ {
+ iterator it=make_iterator(x);
+ safe_mode::detach_equivalent_iterators(it);
+ }
+#endif
+
+ template
+ std::pair emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
+ {
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pairp=
+ this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
+ return std::pair(make_iterator(p.first),p.second);
+ }
+
+ template
+ iterator emplace_hint_impl(
+ iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
+ {
+ BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
+ BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
+ BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
+ std::pairp=
+ this->final_emplace_hint_(
+ static_cast(position.get_node()),
+ BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
+ return make_iterator(p.first);
+ }
+
+ template
+ std::pair
+ range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
+ {
+ node_type* y=header();
+ node_type* z=root();
+
+ while(z){
+ if(!lower(key(z->value()))){
+ z=node_type::from_impl(z->right());
+ }
+ else if(!upper(key(z->value()))){
+ y=z;
+ z=node_type::from_impl(z->left());
+ }
+ else{
+ return std::pair(
+ make_iterator(
+ lower_range(node_type::from_impl(z->left()),z,lower)),
+ make_iterator(
+ upper_range(node_type::from_impl(z->right()),y,upper)));
+ }
+ }
+
+ return std::pair(make_iterator(y),make_iterator(y));
+ }
+
+ template
+ std::pair
+ range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
+ {
+ return std::pair(
+ begin(),
+ make_iterator(upper_range(root(),header(),upper)));
+ }
+
+ template
+ std::pair
+ range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
+ {
+ return std::pair(
+ make_iterator(lower_range(root(),header(),lower)),
+ end());
+ }
+
+ template
+ std::pair
+ range(LowerBounder,UpperBounder,both_unbounded_tag)const
+ {
+ return std::pair(begin(),end());
+ }
+
+ template
+ node_type * lower_range(node_type* top,node_type* y,LowerBounder lower)const
+ {
+ while(top){
+ if(lower(key(top->value()))){
+ y=top;
+ top=node_type::from_impl(top->left());
+ }
+ else top=node_type::from_impl(top->right());
+ }
+
+ return y;
+ }
+
+ template
+ node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
+ {
+ while(top){
+ if(!upper(key(top->value()))){
+ y=top;
+ top=node_type::from_impl(top->left());
+ }
+ else top=node_type::from_impl(top->right());
+ }
+
+ return y;
+ }
+
+#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
+ template
+ void save_(
+ Archive& ar,const unsigned int version,const index_saver_type& sm,
+ ordered_unique_tag)const
+ {
+ super::save_(ar,version,sm);
+ }
+
+ template
+ void load_(
+ Archive& ar,const unsigned int version,const index_loader_type& lm,
+ ordered_unique_tag)
+ {
+ super::load_(ar,version,lm);
+ }
+
+ template
+ void save_(
+ Archive& ar,const unsigned int version,const index_saver_type& sm,
+ ordered_non_unique_tag)const
+ {
+ typedef duplicates_iterator dup_iterator;
+
+ sm.save(
+ dup_iterator(begin().get_node(),end().get_node(),value_comp()),
+ dup_iterator(end().get_node(),value_comp()),
+ ar,version);
+ super::save_(ar,version,sm);
+ }
+
+ template
+ void load_(
+ Archive& ar,const unsigned int version,const index_loader_type& lm,
+ ordered_non_unique_tag)
+ {
+ lm.load(
+ ::boost::bind(
+ &ordered_index_impl::rearranger,this,
+ ::boost::arg<1>(),::boost::arg<2>()),
+ ar,version);
+ super::load_(ar,version,lm);
+ }
+
+ void rearranger(node_type* position,node_type *x)
+ {
+ if(!position||comp_(key(position->value()),key(x->value()))){
+ position=lower_bound(key(x->value())).get_node();
+ }
+ else if(comp_(key(x->value()),key(position->value()))){
+ /* inconsistent rearrangement */
+ throw_exception(
+ archive::archive_exception(
+ archive::archive_exception::other_exception));
+ }
+ else node_type::increment(position);
+
+ if(position!=x){
+ node_impl_type::rebalance_for_erase(
+ x->impl(),header()->parent(),header()->left(),header()->right());
+ node_impl_type::restore(
+ x->impl(),position->impl(),header()->impl());
+ }
+ }
+#endif /* serialization */
+
+protected: /* for the benefit of AugmentPolicy::augmented_interface */
+ key_from_value key;
+ key_compare comp_;
+
+#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
+ BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+};
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+class ordered_index:
+ public AugmentPolicy::template augmented_interface<
+ ordered_index_impl<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy
+ >
+ >::type
+{
+ typedef typename AugmentPolicy::template
+ augmented_interface<
+ ordered_index_impl<
+ KeyFromValue,Compare,
+ SuperMeta,TagList,Category,AugmentPolicy
+ >
+ >::type super;
+public:
+ typedef typename super::ctor_args_list ctor_args_list;
+ typedef typename super::allocator_type allocator_type;
+ typedef typename super::iterator iterator;
+
+ ordered_index& operator=(const ordered_index& x)
+ {
+ this->final()=x.final();
+ return *this;
+ }
+
+protected:
+ ordered_index(
+ const ctor_args_list& args_list,const allocator_type& al):
+ super(args_list,al){}
+
+ ordered_index(const ordered_index& x):super(x){};
+
+ ordered_index(const ordered_index& x,do_not_copy_elements_tag):
+ super(x,do_not_copy_elements_tag()){};
+};
+
+/* comparison */
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator==(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator<(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator!=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return !(x==y);
+}
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator>(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return y
+bool operator>=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return !(x
+bool operator<=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y)
+{
+ return !(x>y);
+}
+
+/* specialized algorithms */
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+void swap(
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& y)
+{
+ x.swap(y);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+/* Boost.Foreach compatibility */
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+inline boost::mpl::true_* boost_foreach_is_noncopyable(
+ boost::multi_index::detail::ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>*&,
+ boost::foreach::tag)
+{
+ return 0;
+}
+
+#undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
+#undef BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF
+
+#endif
diff --git a/include/boost/multi_index/detail/ord_index_impl_fwd.hpp b/include/boost/multi_index/detail/ord_index_impl_fwd.hpp
new file mode 100644
index 0000000..6590ef0
--- /dev/null
+++ b/include/boost/multi_index/detail/ord_index_impl_fwd.hpp
@@ -0,0 +1,128 @@
+/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+ * 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/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_FWD_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_IMPL_FWD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+class ordered_index;
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator==(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator<(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator!=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator>(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator>=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue1,typename Compare1,
+ typename SuperMeta1,typename TagList1,typename Category1,
+ typename AugmentPolicy1,
+ typename KeyFromValue2,typename Compare2,
+ typename SuperMeta2,typename TagList2,typename Category2,
+ typename AugmentPolicy2
+>
+bool operator<=(
+ const ordered_index<
+ KeyFromValue1,Compare1,SuperMeta1,TagList1,Category1,AugmentPolicy1>& x,
+ const ordered_index<
+ KeyFromValue2,Compare2,SuperMeta2,TagList2,Category2,AugmentPolicy2>& y);
+
+template<
+ typename KeyFromValue,typename Compare,
+ typename SuperMeta,typename TagList,typename Category,typename AugmentPolicy
+>
+void swap(
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
+ ordered_index<
+ KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& y);
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/include/boost/multi_index/detail/ord_index_node.hpp b/include/boost/multi_index/detail/ord_index_node.hpp
index 60727e0..ca8d28e 100644
--- a/include/boost/multi_index/detail/ord_index_node.hpp
+++ b/include/boost/multi_index/detail/ord_index_node.hpp
@@ -1,4 +1,4 @@
-/* Copyright 2003-2013 Joaquin M Lopez Munoz.
+/* Copyright 2003-2015 Joaquin M Lopez Munoz.
* 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)
@@ -63,24 +63,24 @@ namespace detail{
enum ordered_index_color{red=false,black=true};
enum ordered_index_side{to_left=false,to_right=true};
-template
+template
struct ordered_index_node_impl; /* fwd decl. */
-template
+template
struct ordered_index_node_std_base
{
typedef typename
boost::detail::allocator::rebind_to<
Allocator,
- ordered_index_node_impl
- >::type::pointer pointer;
+ ordered_index_node_impl
+ >::type::pointer pointer;
typedef typename
boost::detail::allocator::rebind_to<
Allocator,
- ordered_index_node_impl
- >::type::const_pointer const_pointer;
- typedef ordered_index_color& color_ref;
- typedef pointer& parent_ref;
+ ordered_index_node_impl
+ >::type::const_pointer const_pointer;
+ typedef ordered_index_color& color_ref;
+ typedef pointer& parent_ref;
ordered_index_color& color(){return color_;}
ordered_index_color color()const{return color_;}
@@ -116,11 +116,13 @@ private:
#pragma warning(disable:4312 4311)
#endif
-template
+template
struct ordered_index_node_compressed_base
{
- typedef ordered_index_node_impl* pointer;
- typedef const ordered_index_node_impl* const_pointer;
+ typedef ordered_index_node_impl<
+ AugmentPolicy,Allocator>* pointer;
+ typedef const ordered_index_node_impl<
+ AugmentPolicy,Allocator>* const_pointer;
struct color_ref
{
@@ -203,39 +205,44 @@ private:
#endif
#endif
-template
+template
struct ordered_index_node_impl_base:
+ AugmentPolicy::template augmented_node<
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
- mpl::if_c<
- !(has_uintptr_type::value)||
- (alignment_of >::value%2)||
- !(is_same<
- typename boost::detail::allocator::rebind_to<
- Allocator,
- ordered_index_node_impl
- >::type::pointer,
- ordered_index_node_impl*>::value),
- ordered_index_node_std_base,
- ordered_index_node_compressed_base
- >::type
+ mpl::if_c<
+ !(has_uintptr_type::value)||
+ (alignment_of<
+ ordered_index_node_compressed_base
+ >::value%2)||
+ !(is_same<
+ typename boost::detail::allocator::rebind_to<
+ Allocator,
+ ordered_index_node_impl
+ >::type::pointer,
+ ordered_index_node_impl*>::value),
+ ordered_index_node_std_base,
+ ordered_index_node_compressed_base
+ >::type
#else
- ordered_index_node_std_base
+ ordered_index_node_std_base
#endif
+ >::type
{};
-template
-struct ordered_index_node_impl:ordered_index_node_impl_base
+template
+struct ordered_index_node_impl:
+ ordered_index_node_impl_base
{
private:
- typedef ordered_index_node_impl_base super;
+ typedef ordered_index_node_impl_base super;
public:
- typedef typename super::color_ref color_ref;
- typedef typename super::parent_ref parent_ref;
- typedef typename super::pointer pointer;
- typedef typename super::const_pointer const_pointer;
+ typedef typename super::color_ref color_ref;
+ typedef typename super::parent_ref parent_ref;
+ typedef typename super::pointer pointer;
+ typedef typename super::const_pointer const_pointer;
/* interoperability with bidir_node_iterator */
@@ -288,6 +295,7 @@ public:
else x->parent()->right()=y;
y->left()=x;
x->parent()=y;
+ AugmentPolicy::rotate_left(x,y);
}
static pointer minimum(pointer x)
@@ -314,6 +322,7 @@ public:
else x->parent()->left()=y;
y->right()=x;
x->parent()=y;
+ AugmentPolicy::rotate_right(x,y);
}
static void rebalance(pointer x,parent_ref root)
@@ -382,6 +391,7 @@ public:
x->parent()=position;
x->left()=pointer(0);
x->right()=pointer(0);
+ AugmentPolicy::add(x,pointer(header->parent()));
ordered_index_node_impl::rebalance(x,header->parent());
}
@@ -404,7 +414,9 @@ public:
x=y->right();
}
}
+ AugmentPolicy::remove(y,pointer(root));
if(y!=z){
+ AugmentPolicy::copy(z,y);
z->left()->parent()=y; /* relink y in place of z. y is z's successor */
y->left()=z->left();
if(y!=z->right()){
@@ -547,9 +559,10 @@ public:
#endif
};
-template
+template
struct ordered_index_node_trampoline:
ordered_index_node_impl<
+ AugmentPolicy,
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
@@ -557,6 +570,7 @@ struct ordered_index_node_trampoline:
>
{
typedef ordered_index_node_impl<
+ AugmentPolicy,
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
@@ -564,11 +578,12 @@ struct ordered_index_node_trampoline:
> impl_type;
};
-template
-struct ordered_index_node:Super,ordered_index_node_trampoline
+template
+struct ordered_index_node:
+ Super,ordered_index_node_trampoline
{
private:
- typedef ordered_index_node_trampoline trampoline;
+ typedef ordered_index_node_trampoline trampoline;
public:
typedef typename trampoline::impl_type impl_type;
diff --git a/include/boost/multi_index/detail/rnk_index_ops.hpp b/include/boost/multi_index/detail/rnk_index_ops.hpp
new file mode 100644
index 0000000..abe5492
--- /dev/null
+++ b/include/boost/multi_index/detail/rnk_index_ops.hpp
@@ -0,0 +1,298 @@
+/* Copyright 2003-2015 Joaquin M Lopez Munoz.
+ * 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/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_RNK_INDEX_OPS_HPP
+#define BOOST_MULTI_INDEX_DETAIL_RNK_INDEX_OPS_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include /* keep it first to prevent nasty warns in MSVC */
+#include
+#include
+#include
+#include
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Common code for ranked_index memfuns having templatized and
+ * non-templatized versions.
+ */
+
+template
+inline std::size_t ranked_node_size(Pointer x)
+{
+ return x!=Pointer(0)?x->size:0;
+}
+
+template
+inline Pointer ranked_index_nth(std::size_t n,Pointer top,Pointer end_)
+{
+ if(top==Pointer(0)||n>=top->size)return end_;
+
+ for(;;){
+ std::size_t s=ranked_node_size(top->left());
+ if(n==s)return top;
+ if(nleft();
+ else{
+ top=top->right();
+ n-=s+1;
+ }
+ }
+}
+
+template
+inline std::size_t ranked_index_rank(Pointer x,Pointer top)
+{
+ if(top==Pointer(0))return 0;
+ if(x==top->parent())return top->size; /* end */
+
+ std::size_t s=ranked_node_size(x->left());
+ while(x!=top){
+ Pointer z=x->parent();
+ if(x==z->right()){
+ s+=ranked_node_size(z->left())+1;
+ }
+ x=z;
+ }
+ return s;
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_find_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp)
+{
+ typedef typename KeyFromValue::result_type key_type;
+
+ return ranked_index_find_rank(
+ top,y,key,x,comp,
+ mpl::and_<
+ promotes_1st_arg,
+ promotes_2nd_arg >());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleCompare
+>
+inline std::size_t ranked_index_find_rank(
+ Node* top,Node* y,const KeyFromValue& key,
+ const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
+ const CompatibleCompare& comp,mpl::true_)
+{
+ return ranked_index_find_rank(top,y,key,x,comp,mpl::false_());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_find_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp,mpl::false_)
+{
+ if(!top)return 0;
+
+ std::size_t s=top->size,
+ s0=s;
+ Node* y0=y;
+
+ do{
+ if(!comp(key(top->value()),x)){
+ y=top;
+ s-=ranked_node_size(y->right())+1;
+ top=Node::from_impl(top->left());
+ }
+ else top=Node::from_impl(top->right());
+ }while(top);
+
+ return (y==y0||comp(x,key(y->value())))?s0:s;
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_lower_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp)
+{
+ typedef typename KeyFromValue::result_type key_type;
+
+ return ranked_index_lower_bound_rank(
+ top,y,key,x,comp,
+ promotes_2nd_arg());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleCompare
+>
+inline std::size_t ranked_index_lower_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,
+ const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
+ const CompatibleCompare& comp,mpl::true_)
+{
+ return ranked_index_lower_bound_rank(top,y,key,x,comp,mpl::false_());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_lower_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp,mpl::false_)
+{
+ if(!top)return 0;
+
+ std::size_t s=top->size;
+
+ do{
+ if(!comp(key(top->value()),x)){
+ y=top;
+ s-=ranked_node_size(y->right())+1;
+ top=Node::from_impl(top->left());
+ }
+ else top=Node::from_impl(top->right());
+ }while(top);
+
+ return s;
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_upper_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp)
+{
+ typedef typename KeyFromValue::result_type key_type;
+
+ return ranked_index_upper_bound_rank(
+ top,y,key,x,comp,
+ promotes_1st_arg());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleCompare
+>
+inline std::size_t ranked_index_upper_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,
+ const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
+ const CompatibleCompare& comp,mpl::true_)
+{
+ return ranked_index_upper_bound_rank(top,y,key,x,comp,mpl::false_());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::size_t ranked_index_upper_bound_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp,mpl::false_)
+{
+ if(!top)return 0;
+
+ std::size_t s=top->size;
+
+ do{
+ if(comp(x,key(top->value()))){
+ y=top;
+ s-=ranked_node_size(y->right())+1;
+ top=Node::from_impl(top->left());
+ }
+ else top=Node::from_impl(top->right());
+ }while(top);
+
+ return s;
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::pair ranked_index_equal_range_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp)
+{
+ typedef typename KeyFromValue::result_type key_type;
+
+ return ranked_index_equal_range_rank(
+ top,y,key,x,comp,
+ mpl::and_<
+ promotes_1st_arg,
+ promotes_2nd_arg >());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleCompare
+>
+inline std::pair ranked_index_equal_range_rank(
+ Node* top,Node* y,const KeyFromValue& key,
+ const BOOST_DEDUCED_TYPENAME KeyFromValue::result_type& x,
+ const CompatibleCompare& comp,mpl::true_)
+{
+ return ranked_index_equal_range_rank(top,y,key,x,comp,mpl::false_());
+}
+
+template<
+ typename Node,typename KeyFromValue,
+ typename CompatibleKey,typename CompatibleCompare
+>
+inline std::pair ranked_index_equal_range_rank(
+ Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
+ const CompatibleCompare& comp,mpl::false_)
+{
+ if(!top)return std::pair(0,0);
+
+ std::size_t s=top->size;
+
+ do{
+ if(comp(key(top->value()),x)){
+ top=Node::from_impl(top->right());
+ }
+ else if(comp(x,key(top->value()))){
+ y=top;
+ s-=ranked_node_size(y->right())+1;
+ top=Node::from_impl(top->left());
+ }
+ else{
+ return std::pair(
+ s-top->size+
+ ranked_index_lower_bound_rank(
+ Node::from_impl(top->left()),top,key,x,comp,mpl::false_()),
+ s-ranked_node_size(top->right())+
+ ranked_index_upper_bound_rank(
+ Node::from_impl(top->right()),y,key,x,comp,mpl::false_()));
+ }
+ }while(top);
+
+ return std::pair(s,s);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/include/boost/multi_index/ordered_index.hpp b/include/boost/multi_index/ordered_index.hpp
index 267f153..5bcd69d 100644
--- a/include/boost/multi_index/ordered_index.hpp
+++ b/include/boost/multi_index/ordered_index.hpp
@@ -1,36 +1,9 @@
-/* Copyright 2003-2014 Joaquin M Lopez Munoz.
+/* Copyright 2003-2015 Joaquin M Lopez Munoz.
* 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/multi_index for library home page.
- *
- * 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.
- *
*/
#ifndef BOOST_MULTI_INDEX_ORDERED_INDEX_HPP
@@ -41,56 +14,8 @@
#endif
#include /* keep it first to prevent nasty warns in MSVC */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
-#include
-#include
-#include
-#include
-
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
-#include
-#endif
-
-#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
-#include
-#include
-#include
-#include
-#endif
-
-#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
-#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x) \
- detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
- detail::make_obj_guard(x,&ordered_index::check_invariant_); \
- BOOST_JOIN(check_invariant_,__LINE__).touch();
-#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT \
- BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(*this)
-#else
-#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT_OF(x)
-#define BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT
-#endif
namespace boost{
@@ -98,1357 +23,36 @@ namespace multi_index{
namespace detail{
-/* ordered_index adds a layer of ordered indexing to a given Super */
+/* no augment policy for plain ordered indices */
-/* Most of the implementation of unique and non-unique indices is
- * shared. We tell from one another on instantiation time by using
- * these tags.
- */
-
-struct ordered_unique_tag{};
-struct ordered_non_unique_tag{};
-
-template<
- typename KeyFromValue,typename Compare,
- typename SuperMeta,typename TagList,typename Category
->
-class ordered_index:
- BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
-
-#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
- ,public safe_mode::safe_container<
- ordered_index