diff --git a/appveyor.yml b/appveyor.yml
index f01df86..f485522 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-# Copyright 2003-2021 Joaquín M López Muñoz.
+# Copyright 2003-2021 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)
@@ -34,4 +34,4 @@ build: off
test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- - b2 address-model=32 libs/multi_index/test toolset=%TOOLSET% %CXXSTD%
\ No newline at end of file
+ - b2 address-model=32 libs/multi_index/test toolset=%TOOLSET% %CXXSTD%
diff --git a/doc/reference/hash_indices.html b/doc/reference/hash_indices.html
index c3aeb83..1e1c838 100644
--- a/doc/reference/hash_indices.html
+++ b/doc/reference/hash_indices.html
@@ -308,6 +308,16 @@ requirements.
void clear()noexcept;
void swap(index class name& x);
+ template<typename Index> void merge(Index&& x);
+ template<typename Index>
+ std::pair<iterator,bool> merge(
+ Index&& x,typename std::remove_reference_t<Index>::const_iterator i);
+ template<typename Index>
+ void merge(
+ Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last);
+
// observers:
key_from_value key_extractor()const;
@@ -474,7 +484,9 @@ local_iterator
const_local_iterator
-These types are forward iterators.
+These types are forward iterators. They depend only on node_type
and whether
+the index is unique or not (this implies that, for instance, iterators to elements transferred
+from a unique index to a non-unique one will become invalid).
mod'
and back
defined in such a way that
key
is the internal KeyFromValue
object of the index.
+template<typename Index> void merge(Index&& x);
+
++Requires:+ +x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
.
+Effects: +++merge(x,x.begin(),x.end()); +
+template<typename Index> std::pair<iterator,bool> merge(
+ Index&& x,typename std::remove_reference_t<Index>::const_iterator i);
+
+
++Requires:+ +x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
. +i
is a valid dereferenceable iterator ofx
.
+Effects: Does nothing if the source and destination containers are the same; +otherwise, transfers the node of the element referred to byi
into the +multi_index_container
to which the destination index belongs if ++
+Note that no element is copied or destroyed in the process.- the index is non-unique OR no other element exists with + equivalent key,
+- AND insertion is allowed by all other indices of the +
+multi_index_container
.
+Postconditions: If transfer succeeds, for any index in the source container +having the sameiterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to*i
+remain valid and behave as iterators of the destination index.
+Returns: The return value is a pairp
.p.second
+istrue
if and only if transfer took place or the source and destination +containers are the same. Ifp.second
istrue
, +p.first
points to*i
; otherwise,p.first
+points to an element that caused the insertion to be banned. Note that more than +one element can be causing insertion not to be allowed.
+Complexity: If the source and destination containers are the same, +constant; otherwise,O(I(n)+D(x.size()))
.
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise strong. +
+template<typename Index> void merge(
+ Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last);
+
+
++Requires:+x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
. +[first
,last
) is a valid range ofx
.
+Effects: Does nothing if the source and destination containers are the same; +otherwise, for each node in [first
,last
), in this order, +the node is transferred to themulti_index_container
to which the +destination index belongs if ++
+Note that no element is copied or destroyed in the process.- the index is non-unique OR no other element exists with + equivalent key,
+- AND insertion is allowed by all other indices of the +
+multi_index_container
.
+Postconditions: For any index in the source container having the same +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to the transferred elements +remain valid and behave as iterators of the destination index.
+Complexity: If the source and destination containers are the same, +constant; otherwise,O(m*(I(n+m)+D(x.size())))
, where +m
is the number of elements in [first
, +last
).
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise basic. +
Apart from standard hash_function
and key_eq
,
@@ -1275,7 +1370,7 @@ Sequenced indices
-
Revised July 29th 2021
+Revised August 16th 2021
© Copyright 2003-2021 Joaquín M López Muñoz. Distributed under the Boost Software diff --git a/doc/reference/ord_indices.html b/doc/reference/ord_indices.html index 34600f2..af5b491 100644 --- a/doc/reference/ord_indices.html +++ b/doc/reference/ord_indices.html @@ -42,6 +42,7 @@ Ranked indices
KeyFromValue::result_type
.
+iterator
+const_iterator
+
+
+These types depend only on node_type
.
+
+
@@ -911,6 +931,89 @@ with mod'
and back
defined in such a way that
key
is the internal KeyFromValue
object of the index.
+template<typename Index> void merge(Index&& x);
+
+
+Requires:+ +x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
.
+Effects: +++merge(x,x.begin(),x.end()); +
+template<typename Index> std::pair<iterator,bool> merge(
+ Index&& x,typename std::remove_reference_t<Index>::const_iterator i);
+
+
++Requires:+ +x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
. +i
is a valid dereferenceable iterator ofx
.
+Effects: Does nothing if the source and destination containers are the same; +otherwise, transfers the node of the element referred to byi
into the +multi_index_container
to which the destination index belongs if ++
+Note that no element is copied or destroyed in the process.- the index is non-unique OR no other element exists with + equivalent key,
+- AND insertion is allowed by all other indices of the +
+multi_index_container
.
+Postconditions: If transfer succeeds, for any index in the source container +having the sameiterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to*i
+remain valid and behave as iterators of the destination index.
+Returns: The return value is a pairp
.p.second
+istrue
if and only if transfer took place or the source and destination +containers are the same. Ifp.second
istrue
, +p.first
points to*i
; otherwise,p.first
+points to an element that caused the insertion to be banned. Note that more than +one element can be causing insertion not to be allowed.
+Complexity: If the source and destination containers are the same, +constant; otherwise,O(I(n)+D(x.size()))
.
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise strong. +
+template<typename Index> void merge(
+ Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last);
+
+
++Requires:+x
is a non-const reference to an index of a +node-compatible +multi_index_container
.get_allocator()==x.get_allocator()
. +[first
,last
) is a valid range ofx
.
+Effects: Does nothing if the source and destination containers are the same; +otherwise, for each node in [first
,last
), in this order, +the node is transferred to themulti_index_container
to which the +destination index belongs if ++
+Note that no element is copied or destroyed in the process.- the index is non-unique OR no other element exists with + equivalent key,
+- AND insertion is allowed by all other indices of the +
+multi_index_container
.
+Postconditions: For any index in the source container having the same +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to the transferred elements +remain valid and behave as iterators of the destination index.
+Complexity: If the source and destination containers are the same, +constant; otherwise,O(m*(I(n+m)+D(x.size())))
, where +m
is the number of elements in [first
, +last
).
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise basic. +
Apart from standard key_comp
and value_comp
,
@@ -1237,7 +1340,7 @@ Ranked indices
-
Revised July 29th 2021
+Revised August 16th 2021
© Copyright 2003-2021 Joaquín M López Muñoz. Distributed under the Boost Software diff --git a/doc/reference/rnd_indices.html b/doc/reference/rnd_indices.html index dd6a799..f92a9ae 100644 --- a/doc/reference/rnd_indices.html +++ b/doc/reference/rnd_indices.html @@ -40,6 +40,7 @@ Key extraction
std::list
specific list operations at
// list operations:
- void splice(iterator position,index class name& x);
- void splice(iterator position,index class name& x,iterator i);
+ template<typename Index> void splice(const_iterator position,Index&& x);
+ template<typename Index>
+ std::pair<iterator,bool> splice(
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator i);
+ template<typename Index>
void splice(
- iterator position,index class name& x,iterator first,iterator last);
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last);
void remove(const value_type& value);
template<typename Predicate> void remove_if(Predicate pred);
@@ -450,6 +457,15 @@ index specifier. Instantiations are dependent on the following types:
tag
.
+iterator
+const_iterator
+
+
+These types depend only on node_type
.
+
+
@@ -875,56 +891,116 @@ The syntax and behavior of these operations exactly matches those of sequenced indices, but the associated complexity bounds differ in general.
-void splice(iterator position,index class name& x);
+ template<typename Index> void splice(const_iterator position,Index&& x);
-Requires:-position
is a valid iterator of the index. -&x!=this
.
-Effects: Inserts the contents ofx
beforeposition
, -in the same order as they were inx
. Those elements successfully -inserted are erased fromx
.
-Complexity:O(shl(end()-position,x.size()) + x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
-Exception safety: Basic.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +position
is a valid iterator of the index, and must be exactlyend()
+if the source and destination containers are the same.
+Effects: ++splice(position,x,x.begin(),x.end()); +
void splice(iterator position,index class name& x,iterator i);
+
+template<typename Index> std::pair<iterator,bool> splice(
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator i);
+
-Requires:-position
is a valid iterator of the index. -i
is a valid dereferenceable iteratorx
.
-Effects: Inserts the element pointed to byi
before -position
: if insertion is successful, the element is erased from -x
. In the special case&x==this
, no copy or -deletion is performed, and the operation is always successful. If -position==i
, no operation is performed.
-Postconditions: If&x==this
, no iterator or reference -is invalidated.
-Complexity: If&x==this
,O(rel(position,i,i+1))
; -otherwiseO(shl(end()-position,1) + I(n) + D(n))
.
-Exception safety: If&x==this
,nothrow
; -otherwise, strong.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +Ifget_allocator()!=x.get_allocator()
, +value_type
must beCopyInsertable
into the destination +multi_index_container
. +position
is a valid iterator of the index. +i
is a valid dereferenceable iterator ofx
.
+Effects: ++
+Postconditions: If transfer succeeds, for any index in the source container +having the same- (Same container) if the source and destination containers are the same, repositions + the element pointed to by
+i
beforeposition
unless both + iterators refer to the same element.- (Transfer splice) else, if
+get_allocator()==x.get_allocator()
, + transfers the node of the element referred to byi
into the + destinationmulti_index_container
right beforeposition
+ if insertion is allowed by all other indices of themulti_index_container
.- (Destructive splice) else, insertion of
+*i
is tried before +position
; if the operation is successful, the element is erased fromx
. +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to*i
+remain valid and behave as iterators of the destination index.
+Returns: The return value is a pairp
.p.second
+istrue
if and only if insertion (either through transfer or copy insertion) +took place or the source and destination containers are the same. +Ifp.second
istrue
, +p.first
points to the inserted element or to*i
if the +source and destination containers are the same; otherwise,p.first
+points to an element that caused the insertion to be banned. Note that more than +one element can be causing insertion not to be allowed.
+Complexity: If the source and destination containers are the same, +O(rel(position,i',i'+1))
, wherei'
is the projection +ofi
into the index ofposition
; +otherwise,O(shl(end()-position,1) + I(n) + D(x.size()))
.
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise strong.
+Implementation note: The destructive variant of this operation is provided +for reasons of backwards compatibility with previous versions of this library where +allocator equality was not required.
void splice(iterator position,index class name& x,iterator first,iterator last);
+
+template<typename Index> void splice(
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last);
+
-Requires:position
is a valid iterator of the index. -first
andlast
are valid iterators ofx
. -last
is reachable fromfirst
.position
-is not in the range [first
,last
).
-Effects: For each element in the range [first
,last
), -insertion is tried beforeposition
; if the operation is successful, -the element is erased fromx
. In the special case -&x==this
, no copy or deletion is performed, and insertions are -always successful.
-Postconditions: If&x==this
, no iterator or reference -is invalidated.
-Complexity: If&x==this
, -O(rel(position,first,last))
; otherwise -O(shl(end()-position,m) + m*I(n+m) + m*D(x.size()))
-wherem
is the number of elements in [first
,last
).
-Exception safety: If&x==this
,nothrow
; -otherwise, basic.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +Ifget_allocator()!=x.get_allocator()
, +value_type
must beCopyInsertable
into the destination +multi_index_container
. +position
is a valid iterator of the index and does not point to any element in +[first
,last
). +[first
,last
) is a valid range ofx
.
+Effects: ++
+Postconditions: For any index in the source container having the same +- (Same container) if the source and destination containers are the same, repositions all the elements + of [
+first
,last
), in this order, beforeposition
. +- (Transfer splice) else, if
+get_allocator()==x.get_allocator()
, then, for each node in + [first
,last
), in this order, the node is transferred to the +multi_index_container
right beforeposition
+ if insertion is allowed by all other indices of the +multi_index_container
.- (Destructive splice) else, for each element in [
+first
,last
), in this order, + insertion is tried beforeposition
; if the operation is successful, the + element is erased fromx
. +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to the transferred elements +remain valid and behave as iterators of the destination index.
+Complexity: If&x==this
,O(rel(position,first,last))
; +else, if the source and destination containers are the same,O(n)
; +otherwise,O(shl(end()-position,m) + m*(I(n+m) + D(x.size())))
, where +m
is the number of elements in [first
,last
).
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise basic.
+Implementation note: The destructive variant of this operation is provided +for reasons of backwards compatibility with previous versions of this library where +allocator equality was not required.
void remove(const value_type& value);
@@ -973,20 +1049,22 @@ is the number of elements erased.void merge(index class name& x);
-Requires:std::less<value_type>
induces a +Requires: +Eitherget_allocator()==x.get_allocator()
orvalue_type
+isCopyInsertable
into themulti_index_container
. +std::less<value_type>
induces a strict weak ordering overvalue_type
. Both the index andx
are sorted according tostd::less<value_type>
.
-Effects: Attempts to insert every element ofx
into the -corresponding position of the index (according to the order). Elements -successfully inserted are erased fromx
. The resulting sequence +Effects: Attempts to splice every element ofx
into the +corresponding position of the index (according to the order). The resulting sequence is stable, i.e. equivalent elements of either container preserve their relative position. In the special case&x==this
, no operation is performed.
Postconditions: Elements in the index and remaining elements inx
are sorted. -Validity of iterators to the index and of non-erased elements ofx
-references is preserved.
+Validity of iterators and references is preserved, except to elements removed +fromx
ifget_allocator()!=x.get_allocator()
.
Complexity: If&x==this
, constant; otherwiseO(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
Exception safety: If&x==this
,nothrow
; @@ -996,19 +1074,20 @@ otherwise, basic.
template <typename Compare> void merge(index class name& x,Compare comp);
-Requires:Compare
induces a -strict weak ordering overvalue_type
. +Requires: +Eitherget_allocator()==x.get_allocator()
orvalue_type
+isCopyInsertable
into themulti_index_container
. +Compare
induces a strict weak ordering overvalue_type
. Both the index andx
are sorted according tocomp
.
-Effects: Attempts to insert every element ofx
into the -corresponding position of the index (according tocomp
). -Elements successfully inserted are erased fromx
. The resulting +Effects: Attempts to splice every element ofx
into the +corresponding position of the index (according tocomp
). The resulting sequence is stable, i.e. equivalent elements of either container preserve their relative position. In the special case&x==this
, no operation is performed.
Postconditions: Elements in the index and remaining elements inx
are sorted according tocomp
. -Validity of iterators to the index and of non-erased elements ofx
-references is preserved.
+Validity of iterators and references is preserved, except to elements removed +fromx
ifget_allocator()!=x.get_allocator()
.
Complexity: If&x==this
, constant; otherwiseO(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
Exception safety: If&x==this
,nothrow
; @@ -1160,9 +1239,9 @@ Key extraction
-Revised May 9th 2020
+Revised August 16th 2021
-© Copyright 2003-2020 Joaquín M López Muñoz. +
© Copyright 2003-2021 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 index 9904b54..bfa3b44 100644 --- a/doc/reference/rnk_indices.html +++ b/doc/reference/rnk_indices.html @@ -42,6 +42,7 @@ Hashed indices @@ -473,6 +474,15 @@ These types are subject to the same requirements as specified for ordered indices.
+Nested types
+ +iterator
+ +
+const_iterator+These types depend only on+node_type
. +Rank operations
@@ -637,7 +647,7 @@ Hashed indices
-Revised July 29th 2021
+Revised August 14th 2021
© Copyright 2003-2021 Joaquín M López Muñoz. Distributed under the Boost Software diff --git a/doc/reference/seq_indices.html b/doc/reference/seq_indices.html index 385fa1b..80e0f14 100644 --- a/doc/reference/seq_indices.html +++ b/doc/reference/seq_indices.html @@ -40,6 +40,7 @@ Random access indices
@@ -88,7 +116,7 @@ Acknowledgements
- Complexity signature
- Instantiation types
+- Nested types
- Constructors, copy and assignment
- Iterators
- Capacity operations
@@ -299,10 +300,16 @@ most important differences are: // list operations: - void splice(iterator position,index class name& x); - void splice(iterator position,index class name& x,iterator i); + template<typename Index> void splice(const_iterator position,Index&& x); + template<typename Index> + std::pair<iterator,bool> splice( + const_iterator position,Index&& x, + typename std::remove_reference_t<Index>::const_iterator i); + template<typename Index> void splice( - iterator position,index class name& x,iterator first,iterator last); + const_iterator position,Index&& x, + typename std::remove_reference_t<Index>::const_iterator first, + typename std::remove_reference_t<Index>::const_iterator last); void remove(const value_type& value); template<typename Predicate> void remove_if(Predicate pred); @@ -420,6 +427,15 @@ index specifier. Instantiations are dependent on the following types:tag
. +Nested types
+ +iterator
+ +
+const_iterator+These types depend only on+node_type
. +Constructors, copy and assignment
@@ -802,62 +818,122 @@ is rethrown.
Sequenced indices provide the full set of list operations found in -
-std::list
; the semantics of these member functions, however, -differ from that ofstd::list
in some cases as insertions -might not succeed due to banning by other indices. Similarly, the complexity +std::list
, extended in some cases such assplice
; +the semantics of these member functions, however, +typically differs from that ofstd::list
as insertions +may not succeed due to banning by other indices. Similarly, the complexity of the operations may depend on the other indices belonging to the samemulti_index_container
.void splice(iterator position,index class name& x);
+template<typename Index> void splice(const_iterator position,Index&& x);
-Requires:-position
is a valid iterator of the index. -&x!=this
.
-Effects: Inserts the contents ofx
beforeposition
, -in the same order as they were inx
. Those elements successfully -inserted are erased fromx
.
-Complexity:O(x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
-Exception safety: Basic.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +position
is a valid iterator of the index, and must be exactlyend()
+if the source and destination containers are the same.
+Effects: ++splice(position,x,x.begin(),x.end()); +void splice(iterator position,index class name& x,iterator i);
++template<typename Index> std::pair<iterator,bool> splice(
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator i); +-Requires:-position
is a valid iterator of the index. -i
is a valid dereferenceable iteratorx
.
-Effects: Inserts the element pointed to byi
before -position
: if insertion is successful, the element is erased from -x
. In the special case&x==this
, no copy or -deletion is performed, and the operation is always successful. If -position==i
, no operation is performed.
-Postconditions: If&x==this
, no iterator or reference -is invalidated.
-Complexity: If&x==this
, constant; otherwise -O(I(n) + D(n))
.
-Exception safety: If&x==this
,nothrow
; -otherwise, strong.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +Ifget_allocator()!=x.get_allocator()
, +value_type
must beCopyInsertable
into the destination +multi_index_container
. +position
is a valid iterator of the index. +i
is a valid dereferenceable iterator ofx
.
+Effects: ++
+Postconditions: If transfer succeeds, for any index in the source container +having the same- (Same container) if the source and destination containers are the same, repositions + the element pointed to by
+i
beforeposition
unless both + iterators refer to the same element.- (Transfer splice) else, if
+get_allocator()==x.get_allocator()
, + transfers the node of the element referred to byi
into the + destinationmulti_index_container
right beforeposition
+ if insertion is allowed by all other indices of themulti_index_container
.- (Destructive splice) else, insertion of
+*i
is tried before +position
; if the operation is successful, the element is erased fromx
. +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to*i
+remain valid and behave as iterators of the destination index.
+Returns: The return value is a pairp
.p.second
+istrue
if and only if insertion (either through transfer or copy insertion) +took place or the source and destination containers are the same. +Ifp.second
istrue
, +p.first
points to the inserted element or to*i
if the +source and destination containers are the same; otherwise,p.first
+points to an element that caused the insertion to be banned. Note that more than +one element can be causing insertion not to be allowed.
+Complexity: If the source and destination containers are the same, +constant; otherwise,O(I(n)+D(x.size()))
.
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise strong.
+Implementation note: The destructive variant of this operation is provided +for reasons of backwards compatibility with previous versions of this library where +allocator equality was not required.void splice(iterator position,index class name& x,iterator first,iterator last);
++template<typename Index> void splice(
+ const_iterator position,Index&& x,
+ typename std::remove_reference_t<Index>::const_iterator first,
+ typename std::remove_reference_t<Index>::const_iterator last); +-Requires:position
is a valid iterator of the index. -first
andlast
are valid iterators ofx
. -last
is reachable fromfirst
.position
-is not in the range [first
,last
).
-Effects: For each element in the range [first
,last
), -insertion is tried beforeposition
; if the operation is successful, -the element is erased fromx
. In the special case -&x==this
, no copy or deletion is performed, and insertions are -always successful.
-Postconditions: If&x==this
, no iterator or reference -is invalidated.
-Complexity: If&x==this
, constant; otherwise -O(m*I(n+m) + m*D(x.size()))
wherem
is the number -of elements in [first
,last
).
-Exception safety: If&x==this
,nothrow
; -otherwise, basic.
+Requires:x
is a non-const reference to an index of a +node-compatible +multi_index_container
. +Ifget_allocator()!=x.get_allocator()
, +value_type
must beCopyInsertable
into the destination +multi_index_container
. +position
is a valid iterator of the index and does not point to any element in +[first
,last
). +[first
,last
) is a valid range ofx
.
+Effects: ++
+Postconditions: For any index in the source container having the same +- (Same container) if the source and destination containers are the same, repositions all the elements + of [
+first
,last
), in this order, beforeposition
. +- (Transfer splice) else, if
+get_allocator()==x.get_allocator()
, then, for each node in + [first
,last
), in this order, the node is transferred to the +multi_index_container
right beforeposition
+ if insertion is allowed by all other indices of the +multi_index_container
.- (Destructive splice) else, for each element in [
+first
,last
), in this order, + insertion is tried beforeposition
; if the operation is successful, the + element is erased fromx
. +iterator
/const_iterator
types as the corresponding +index in the destination container, iterators referring to the transferred elements +remain valid and behave as iterators of the destination index.
+Complexity: If&x==this
, constant; else, if +the source and destination containers are the same,O(m)
; +otherwise,O(m*(I(n+m)+D(x.size())))
, where +m
is the number of elements in [first
,last
).
+Exception safety: If the source and destination containers are the same, +nothrow
; otherwise basic.
+Implementation note: The destructive variant of this operation is provided +for reasons of backwards compatibility with previous versions of this library where +allocator equality was not required.void remove(const value_type& value);
@@ -906,20 +982,22 @@ is the number of elements erased.
void merge(index class name& x);
-Requires:std::less<value_type>
induces a +Requires: +Eitherget_allocator()==x.get_allocator()
orvalue_type
+isCopyInsertable
into themulti_index_container
. +std::less<value_type>
induces a strict weak ordering overvalue_type
. Both the index andx
are sorted according tostd::less<value_type>
.
-Effects: Attempts to insert every element ofx
into the -corresponding position of the index (according to the order). Elements -successfully inserted are erased fromx
. The resulting sequence +Effects: Attempts to splice every element ofx
into the +corresponding position of the index (according to the order). The resulting sequence is stable, i.e. equivalent elements of either container preserve their relative position. In the special case&x==this
, no operation is performed.
Postconditions: Elements in the index and remaining elements inx
are sorted. -Validity of iterators to the index and of non-erased elements ofx
-references is preserved.
+Validity of iterators and references is preserved, except to elements removed +fromx
ifget_allocator()!=x.get_allocator()
.
Complexity: If&x==this
, constant; otherwiseO(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
Exception safety: If&x==this
,nothrow
; @@ -929,19 +1007,20 @@ otherwise, basic.
template <typename Compare> void merge(index class name& x,Compare comp);
-Requires:Compare
induces a -strict weak ordering overvalue_type
. +Requires: +Eitherget_allocator()==x.get_allocator()
orvalue_type
+isCopyInsertable
into themulti_index_container
. +Compare
induces a strict weak ordering overvalue_type
. Both the index andx
are sorted according tocomp
.
-Effects: Attempts to insert every element ofx
into the -corresponding position of the index (according tocomp
). -Elements successfully inserted are erased fromx
. The resulting +Effects: Attempts to splice every element ofx
into the +corresponding position of the index (according tocomp
). The resulting sequence is stable, i.e. equivalent elements of either container preserve their relative position. In the special case&x==this
, no operation is performed.
Postconditions: Elements in the index and remaining elements inx
are sorted according tocomp
. -Validity of iterators to the index and of non-erased elements ofx
-references is preserved.
+Validity of iterators and references is preserved, except to elements removed +fromx
ifget_allocator()!=x.get_allocator()
.
Complexity: If&x==this
, constant; otherwiseO(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))
.
Exception safety: If&x==this
,nothrow
; @@ -1095,9 +1174,9 @@ Random access indices
-Revised May 9th 2020
+Revised August 16th 2021
-© Copyright 2003-2020 Joaquín M López Muñoz. +
© Copyright 2003-2021 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/release_notes.html b/doc/release_notes.html index 11046c2..ef7ec43 100644 --- a/doc/release_notes.html +++ b/doc/release_notes.html @@ -72,6 +72,34 @@ Acknowledgements
- Added
+contains
to key-based indices (issue #35).- Added
+merge
operations to key-based indices. The functionality goes beyond + the standard specification for (unordered) associative containers in a number of ways, + most notably: ++
+- The source index can be of any type, including non key-based indices.
+- Partial merge is provided: for instance,
+x.merge(y,first,last)
+ merges only the elements ofy
within [first
,last
). +- Previous versions of
+splice
for sequenced and random access indices + were destructive, i.e. elements were copy-inserted into the destination and then erased + from the source. Now,splice
is based on node transfer much asmerge
+ in key-based indices, and has been similarly extended to accept source indices of any type: + in fact,splice
can be regarded as a frontend to the same functionality + provided bymerge
in key-based indices. For reasons of backwards compatibility, + the destructive behavior ofsplice
has been retained in the case that the + source and destination containers have unequal allocators. +- The fact has been documented that index iterator types do only depend on
+node_type
, + (except for hashed indices, where uniqueness/non-uniqueness is also a dependency). This has + implications on the validity of iterators to elements transferred bymerge
or +splice
. This property is a variant of what has been called + SCARY iterators in the C++ standard mailing lists. + SCARYness is currently (August 2021) not mandated for standard containers. +- Iterator SCARYness is now also preserved in safe mode. +
- - Added node extraction and insertion + Added node extraction and insertion following the analogous interface of associative containers as introduced in C++17. This feature has also been extended to non key-based indices, in contrast to C++ standard library sequence containers, which do not provide such functionality. @@ -695,7 +723,7 @@ Acknowledgements
-Revised July 29th 2021
+Revised August 16th 2021
© Copyright 2003-2021 Joaquín M López Muñoz. Distributed under the Boost Software diff --git a/doc/tutorial/basics.html b/doc/tutorial/basics.html index 8a5a6fa..8f14652 100644 --- a/doc/tutorial/basics.html +++ b/doc/tutorial/basics.html @@ -62,7 +62,6 @@ Index types
- Projection of iterators
-- Node handling operations
- Complexity and exception safety
project
can also be used with
tags.
-
-Using direct node manipulation, elements can be passed between
-multi_index_container
s without actually copying them:
-
- --// move an employee to the retiree archive -void move_to_retirement(int ssnumber,employee_set& es,employee_set& archive) -{ - // extract the employee with given SS number to a node handle - employee_set_by_ssn::node_type node=es.get<ssn>().extract(ssnumber); - - if(!node.empty()){ // employee found - // re-insert into archive (note the use of std::move) - archive.insert(std::move(node)); - } -} -
-In the example, the internal node is transferred as-is from es
to archive
,
-which is more efficient than erasing from the source and recreating in destination.
-node_type
is a move-only class used to pass nodes around, and its interface follows
-that of the homonym type
-for C++ associative containers (set containers version). Boost.MultiIndex provides node extraction
-and insertion operations for all index types, including sequenced ones (by contrast,
-std::list
does not have such features):
-
- --multi_index_container< - int, - indexed_by< - sequenced<>, - ordered_unique<identity<int> > - > -> src; - -multi_index_container< - int, - indexed_by< - sequenced<>, - ordered_non_unique<identity<int>, std::greater<int> > - > -> dst; - -... - -// transfer even numbers from src to dst -for(auto first=src.begin(),last=src.end();first!=last;){ - if(*first%2==0) dst.insert(dst.end(),src.extract(first++)); - else ++first; -} -
-Note that src
and dst
are of different types,
-yet transfer is possible. Two multi_index_container
s are
-node-compatible (that is, they use the same node_type
) if
-they have the same element and allocator types and their respective indices match
-one by one without regard to whether they are unique or non-unique or to
-their particular configuration parameters: they are both ordered, or
-both sequenced, etc.
-
@@ -1317,9 +1250,9 @@ Index types
-
Revised May 9th 2020
+Revised August 16th 2021
-© Copyright 2003-2020 Joaquín M López Muñoz. +
© Copyright 2003-2021 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 b1f13bc..dee316e 100644
--- a/doc/tutorial/indices.html
+++ b/doc/tutorial/indices.html
@@ -55,6 +55,7 @@ Key extraction
iterator_to
-Hashed indices replicate the interface as std::unordered_set
and
+Hashed indices replicate the interface of 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.
@@ -774,6 +775,113 @@ in scenarios where access via iterators is not suitable or desireable:
+Using direct node manipulation, elements can be passed between
+multi_index_container
s without actually copying them:
+
+ ++// move an employee to the retiree archive +void move_to_retirement(int ssnumber,employee_set& es,employee_set& archive) +{ + // assume employee_set has an index on SS number(not shown before) + // extract the employee with given SS number to a node handle + employee_set_by_ssn::node_type node=es.get<ssn>().extract(ssnumber); + + if(!node.empty()){ // employee found + // re-insert into archive (note the use of std::move) + archive.insert(std::move(node)); + } +} +
+In the example, the internal node is transferred as-is from es
to archive
,
+which is more efficient than erasing from the source and recreating in destination.
+node_type
is a move-only class used to pass nodes around, and its interface follows
+that of the homonym type
+for C++ associative containers (set containers version). Boost.MultiIndex provides node extraction
+and insertion operations for all index types, including sequenced ones (by contrast,
+std::list
does not have such features):
+
+ ++multi_index_container< + int, + indexed_by< + sequenced<>, + ordered_unique<identity<int> > + > +> src; + +multi_index_container< + int, + indexed_by< + sequenced<>, + ordered_non_unique<identity<int>, std::greater<int> > + > +> dst; + +... + +// transfer even numbers from src to dst +for(auto first=src.begin(),last=src.end();first!=last;){ + if(*first%2==0) dst.insert(dst.end(),src.extract(first++)); + else ++first; +} +
+Note that src
and dst
are of different types,
+yet transfer is possible. Two multi_index_container
s are
+node-compatible (that is, they use the same node_type
) if
+they have the same element and allocator types and their respective indices match
+one by one without regard to whether they are unique or non-unique or to
+their particular configuration parameters: they are both ordered, or
+both sequenced, etc.
+
+Alternatively, direct node transfer between two containers can be done without
+keeping intervening node_type
s thanks to merge
(key-based
+indices) and splice
(non key-based indices).
+
+ ++// move older employees to retirement +void move_to_retirement_by_age( + int max_age,employee_set& es,employee_set& archive) +{ + // assume employee_set has an index on age (not shown before) + employee_set_by_age& ea=es.get<age>(); + + // archive employees with age>max_age + archive.merge(ea,ea.upper_bound(max_age),ea.end()); +} + +... + +// transfer even numbers from src to dst +for(auto first=src.begin(),last=src.end();first!=last;){ + if(*first%2==0) dst.splice(dst.end(),src,first++); + else ++first; +} +
+There are overloads of merge
/splice
for transferring a single element,
+a range between two iterators and an entire container: for further details, consult
+for instance the reference for ordered indices and for
+sequenced indices
+(the rest of indices provide one interface or the other).
+Please note that sequenced and random access indices do also have an operation called merge
,
+but this follows the specification of std::list::merge
, which has a somewhat
+different behavior (source and destination are required to be ordered by the same criterion). This is
+a rather confusing naming issue that Boost.MultiIndex simply inherits from the C++ standard.
+
@@ -821,7 +929,7 @@ Key extraction
-
Revised July 29th 2021
+Revised August 16th 2021
© Copyright 2003-2021 Joaquín M López Muñoz.
Distributed under the Boost Software
diff --git a/include/boost/multi_index/detail/any_container_view.hpp b/include/boost/multi_index/detail/any_container_view.hpp
new file mode 100644
index 0000000..6432b35
--- /dev/null
+++ b/include/boost/multi_index/detail/any_container_view.hpp
@@ -0,0 +1,76 @@
+/* Copyright 2003-2021 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_ANY_CONTAINER_VIEW_HPP
+#define BOOST_MULTI_INDEX_DETAIL_ANY_CONTAINER_VIEW_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* type-erased, non-owning view over a ConstIterator-container's range */
+
+template