cpp-btree: Add support for uncopyable/move-only map/multimap value types
This commit is contained in:
3
src/3rdparty/cpp-btree/README
vendored
3
src/3rdparty/cpp-btree/README
vendored
@@ -40,6 +40,9 @@ Changes include:
|
|||||||
- Adding key_comp
|
- Adding key_comp
|
||||||
- Adding move constructors/assignment.
|
- Adding move constructors/assignment.
|
||||||
- No longer #define NDEBUG if unset, this can clash with other headers, test for BTREE_DEBUG being defined instead
|
- No longer #define NDEBUG if unset, this can clash with other headers, test for BTREE_DEBUG being defined instead
|
||||||
|
- Add noexcept to swap-based move constructors and copy/move assignment operator
|
||||||
|
- Remove use of deprecated std::allocator::rebind type
|
||||||
|
- Adding support for uncopyable/move-only map/multimap values (not keys).
|
||||||
|
|
||||||
CMakeLists-pthreads-fix.txt is a modified copy of CMakeLists.txt which includes -lpthreads when building the tests/benchmarks.
|
CMakeLists-pthreads-fix.txt is a modified copy of CMakeLists.txt which includes -lpthreads when building the tests/benchmarks.
|
||||||
Using this instead fixes compilation on some platforms.
|
Using this instead fixes compilation on some platforms.
|
||||||
|
124
src/3rdparty/cpp-btree/btree.h
vendored
124
src/3rdparty/cpp-btree/btree.h
vendored
@@ -649,9 +649,14 @@ class btree_node {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void insert_value_common(int i);
|
||||||
|
|
||||||
|
public:
|
||||||
// Inserts the value x at position i, shifting all existing values and
|
// Inserts the value x at position i, shifting all existing values and
|
||||||
// children at positions >= i to the right by 1.
|
// children at positions >= i to the right by 1.
|
||||||
void insert_value(int i, const value_type &x);
|
template <typename... Args>
|
||||||
|
void insert_value(int i, Args&&... args);
|
||||||
|
|
||||||
// Removes the value at position i, shifting all existing values and children
|
// Removes the value at position i, shifting all existing values and children
|
||||||
// at positions > i to the left by 1.
|
// at positions > i to the left by 1.
|
||||||
@@ -709,8 +714,9 @@ class btree_node {
|
|||||||
void value_init(int i) {
|
void value_init(int i) {
|
||||||
new (&fields_.values[i]) mutable_value_type;
|
new (&fields_.values[i]) mutable_value_type;
|
||||||
}
|
}
|
||||||
void value_init(int i, const value_type &x) {
|
template <typename... Args>
|
||||||
new (&fields_.values[i]) mutable_value_type(x);
|
void value_init_args(int i, Args&&... args) {
|
||||||
|
new (&fields_.values[i]) mutable_value_type(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
void value_destroy(int i) {
|
void value_destroy(int i) {
|
||||||
fields_.values[i].~mutable_value_type();
|
fields_.values[i].~mutable_value_type();
|
||||||
@@ -1002,45 +1008,65 @@ class btree : public Params::key_compare {
|
|||||||
|
|
||||||
// Inserts a value into the btree only if it does not already exist. The
|
// Inserts a value into the btree only if it does not already exist. The
|
||||||
// boolean return value indicates whether insertion succeeded or failed. The
|
// boolean return value indicates whether insertion succeeded or failed. The
|
||||||
// ValuePointer type is used to avoid instatiating the value unless the key
|
// Args&&... type is used to avoid instatiating the value unless the key
|
||||||
// is being inserted. Value is not dereferenced if the key already exists in
|
// is being inserted. See btree_map::operator[].
|
||||||
// the btree. See btree_map::operator[].
|
template <typename... Args>
|
||||||
template <typename ValuePointer>
|
std::pair<iterator,bool> insert_unique_args(const key_type &key, Args&&... args);
|
||||||
std::pair<iterator,bool> insert_unique(const key_type &key, ValuePointer value);
|
|
||||||
|
|
||||||
// Inserts a value into the btree only if it does not already exist. The
|
// Inserts a value into the btree only if it does not already exist. The
|
||||||
// boolean return value indicates whether insertion succeeded or failed.
|
// boolean return value indicates whether insertion succeeded or failed.
|
||||||
std::pair<iterator,bool> insert_unique(const value_type &v) {
|
std::pair<iterator,bool> insert_unique(const value_type &v) {
|
||||||
return insert_unique(params_type::key(v), &v);
|
return insert_unique_args(params_type::key(v), v);
|
||||||
}
|
}
|
||||||
|
std::pair<iterator,bool> insert_unique(value_type &&v) {
|
||||||
|
return insert_unique_args(params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator insert_unique_hint_args(iterator position, const key_type &key, Args&&... args);
|
||||||
|
|
||||||
// Insert with hint. Check to see if the value should be placed immediately
|
// Insert with hint. Check to see if the value should be placed immediately
|
||||||
// before position in the tree. If it does, then the insertion will take
|
// before position in the tree. If it does, then the insertion will take
|
||||||
// amortized constant time. If not, the insertion will take amortized
|
// amortized constant time. If not, the insertion will take amortized
|
||||||
// logarithmic time as if a call to insert_unique(v) were made.
|
// logarithmic time as if a call to insert_unique(v) were made.
|
||||||
iterator insert_unique(iterator position, const value_type &v);
|
iterator insert_unique(iterator position, const value_type &v) {
|
||||||
|
return insert_unique_hint_args(position, params_type::key(v), v);
|
||||||
|
}
|
||||||
|
iterator insert_unique(iterator position, value_type &&v) {
|
||||||
|
return insert_unique_hint_args(position, params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
// Insert a range of values into the btree.
|
// Insert a range of values into the btree.
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
void insert_unique(InputIterator b, InputIterator e);
|
void insert_unique(InputIterator b, InputIterator e);
|
||||||
|
|
||||||
// Inserts a value into the btree. The ValuePointer type is used to avoid
|
// Inserts a value into the btree. The Args&&... type is used to avoid
|
||||||
// instatiating the value unless the key is being inserted. Value is not
|
// instatiating the value unless the key is being inserted. See
|
||||||
// dereferenced if the key already exists in the btree. See
|
|
||||||
// btree_map::operator[].
|
// btree_map::operator[].
|
||||||
template <typename ValuePointer>
|
template <typename... Args>
|
||||||
iterator insert_multi(const key_type &key, ValuePointer value);
|
iterator insert_multi_args(const key_type &key, Args&&... args);
|
||||||
|
|
||||||
// Inserts a value into the btree.
|
// Inserts a value into the btree.
|
||||||
iterator insert_multi(const value_type &v) {
|
iterator insert_multi(const value_type &v) {
|
||||||
return insert_multi(params_type::key(v), &v);
|
return insert_multi_args(params_type::key(v), v);
|
||||||
}
|
}
|
||||||
|
iterator insert_multi(value_type &&v) {
|
||||||
|
return insert_multi_args(params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator insert_multi_hint_args(iterator position, const key_type &key, Args&&... args);
|
||||||
|
|
||||||
// Insert with hint. Check to see if the value should be placed immediately
|
// Insert with hint. Check to see if the value should be placed immediately
|
||||||
// before position in the tree. If it does, then the insertion will take
|
// before position in the tree. If it does, then the insertion will take
|
||||||
// amortized constant time. If not, the insertion will take amortized
|
// amortized constant time. If not, the insertion will take amortized
|
||||||
// logarithmic time as if a call to insert_multi(v) were made.
|
// logarithmic time as if a call to insert_multi(v) were made.
|
||||||
iterator insert_multi(iterator position, const value_type &v);
|
iterator insert_multi(iterator position, const value_type &v) {
|
||||||
|
return insert_multi_hint_args(position, params_type::key(v), v);
|
||||||
|
}
|
||||||
|
iterator insert_multi(iterator position, value_type &&v) {
|
||||||
|
return insert_multi_hint_args(position, params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
// Insert a range of values into the btree.
|
// Insert a range of values into the btree.
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
@@ -1305,9 +1331,12 @@ class btree : public Params::key_compare {
|
|||||||
return iter.node ? iter : end();
|
return iter.node ? iter : end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator internal_insert_common(iterator iter);
|
||||||
|
|
||||||
// Inserts a value into the btree immediately before iter. Requires that
|
// Inserts a value into the btree immediately before iter. Requires that
|
||||||
// key(v) <= iter.key() and (--iter).key() <= key(v).
|
// key(v) <= iter.key() and (--iter).key() <= key(v).
|
||||||
iterator internal_insert(iterator iter, const value_type &v);
|
template <typename... Args>
|
||||||
|
iterator internal_insert(iterator iter, Args&&... args);
|
||||||
|
|
||||||
// Returns an iterator pointing to the first value >= the value "iter" is
|
// Returns an iterator pointing to the first value >= the value "iter" is
|
||||||
// pointing at. Note that "iter" might be pointing to an invalid location as
|
// pointing at. Note that "iter" might be pointing to an invalid location as
|
||||||
@@ -1420,10 +1449,15 @@ class btree : public Params::key_compare {
|
|||||||
|
|
||||||
////
|
////
|
||||||
// btree_node methods
|
// btree_node methods
|
||||||
template <typename P>
|
template <typename P> template <typename... Args>
|
||||||
inline void btree_node<P>::insert_value(int i, const value_type &x) {
|
inline void btree_node<P>::insert_value(int i, Args&&... args) {
|
||||||
dbg_assert(i <= count());
|
dbg_assert(i <= count());
|
||||||
value_init(count(), x);
|
value_init_args(count(), std::forward<Args>(args)...);
|
||||||
|
insert_value_common(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P>
|
||||||
|
inline void btree_node<P>::insert_value_common(int i) {
|
||||||
for (int j = count(); j > i; --j) {
|
for (int j = count(); j > i; --j) {
|
||||||
value_swap(j, this, j - 1);
|
value_swap(j, this, j - 1);
|
||||||
}
|
}
|
||||||
@@ -1576,7 +1610,7 @@ void btree_node<P>::split(btree_node *dest, int insert_position) {
|
|||||||
|
|
||||||
// The split key is the largest value in the left sibling.
|
// The split key is the largest value in the left sibling.
|
||||||
set_count(count() - 1);
|
set_count(count() - 1);
|
||||||
parent()->insert_value(position(), value_type());
|
parent()->insert_value(position());
|
||||||
value_swap(count(), parent(), position());
|
value_swap(count(), parent(), position());
|
||||||
value_destroy(count());
|
value_destroy(count());
|
||||||
parent()->set_child(position() + 1, dest);
|
parent()->set_child(position() + 1, dest);
|
||||||
@@ -1741,9 +1775,9 @@ btree<P>::btree(const self_type &x)
|
|||||||
assign(x);
|
assign(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P> template <typename ValuePointer>
|
template <typename P> template <typename... Args>
|
||||||
std::pair<typename btree<P>::iterator, bool>
|
std::pair<typename btree<P>::iterator, bool>
|
||||||
btree<P>::insert_unique(const key_type &key, ValuePointer value) {
|
btree<P>::insert_unique_args(const key_type &key, Args&&... args) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
*mutable_root() = new_leaf_root_node(1);
|
*mutable_root() = new_leaf_root_node(1);
|
||||||
}
|
}
|
||||||
@@ -1761,34 +1795,33 @@ btree<P>::insert_unique(const key_type &key, ValuePointer value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(internal_insert(iter, *value), true);
|
return std::make_pair(internal_insert(iter, std::forward<Args>(args)...), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P>
|
template <typename P> template <typename... Args>
|
||||||
inline typename btree<P>::iterator
|
inline typename btree<P>::iterator
|
||||||
btree<P>::insert_unique(iterator position, const value_type &v) {
|
btree<P>::insert_unique_hint_args(iterator position, const key_type &key, Args&&... args) {
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
const key_type &key = params_type::key(v);
|
|
||||||
const iterator end = this->end();
|
const iterator end = this->end();
|
||||||
if (position == end || compare_keys(key, position.key())) {
|
if (position == end || compare_keys(key, position.key())) {
|
||||||
iterator prev = position;
|
iterator prev = position;
|
||||||
if (position == begin() || compare_keys((--prev).key(), key)) {
|
if (position == begin() || compare_keys((--prev).key(), key)) {
|
||||||
// prev.key() < key < position.key()
|
// prev.key() < key < position.key()
|
||||||
return internal_insert(position, v);
|
return internal_insert(position, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
} else if (compare_keys(position.key(), key)) {
|
} else if (compare_keys(position.key(), key)) {
|
||||||
iterator next = position;
|
iterator next = position;
|
||||||
++next;
|
++next;
|
||||||
if (next == end || compare_keys(key, next.key())) {
|
if (next == end || compare_keys(key, next.key())) {
|
||||||
// position.key() < key < next.key()
|
// position.key() < key < next.key()
|
||||||
return internal_insert(next, v);
|
return internal_insert(next, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// position.key() == key
|
// position.key() == key
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insert_unique(v).first;
|
return insert_unique_args(key, std::forward<Args>(args)...).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P> template <typename InputIterator>
|
template <typename P> template <typename InputIterator>
|
||||||
@@ -1798,9 +1831,9 @@ void btree<P>::insert_unique(InputIterator b, InputIterator e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P> template <typename ValuePointer>
|
template <typename P> template <typename... Args>
|
||||||
typename btree<P>::iterator
|
typename btree<P>::iterator
|
||||||
btree<P>::insert_multi(const key_type &key, ValuePointer value) {
|
btree<P>::insert_multi_args(const key_type &key, Args&&... args) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
*mutable_root() = new_leaf_root_node(1);
|
*mutable_root() = new_leaf_root_node(1);
|
||||||
}
|
}
|
||||||
@@ -1809,31 +1842,31 @@ btree<P>::insert_multi(const key_type &key, ValuePointer value) {
|
|||||||
if (!iter.node) {
|
if (!iter.node) {
|
||||||
iter = end();
|
iter = end();
|
||||||
}
|
}
|
||||||
return internal_insert(iter, *value);
|
return internal_insert(iter, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P>
|
|
||||||
|
template <typename P> template <typename... Args>
|
||||||
typename btree<P>::iterator
|
typename btree<P>::iterator
|
||||||
btree<P>::insert_multi(iterator position, const value_type &v) {
|
btree<P>::insert_multi_hint_args(iterator position, const key_type &key, Args&&... args) {
|
||||||
if (!empty()) {
|
if (!empty()) {
|
||||||
const key_type &key = params_type::key(v);
|
|
||||||
const iterator end = this->end();
|
const iterator end = this->end();
|
||||||
if (position == end || !compare_keys(position.key(), key)) {
|
if (position == end || !compare_keys(position.key(), key)) {
|
||||||
iterator prev = position;
|
iterator prev = position;
|
||||||
if (position == begin() || !compare_keys(key, (--prev).key())) {
|
if (position == begin() || !compare_keys(key, (--prev).key())) {
|
||||||
// prev.key() <= key <= position.key()
|
// prev.key() <= key <= position.key()
|
||||||
return internal_insert(position, v);
|
return internal_insert(position, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iterator next = position;
|
iterator next = position;
|
||||||
++next;
|
++next;
|
||||||
if (next == end || !compare_keys(next.key(), key)) {
|
if (next == end || !compare_keys(next.key(), key)) {
|
||||||
// position.key() < key <= next.key()
|
// position.key() < key <= next.key()
|
||||||
return internal_insert(next, v);
|
return internal_insert(next, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insert_multi(v);
|
return insert_multi_args(key, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P> template <typename InputIterator>
|
template <typename P> template <typename InputIterator>
|
||||||
@@ -2202,7 +2235,7 @@ inline IterType btree<P>::internal_last(IterType iter) {
|
|||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
inline typename btree<P>::iterator
|
inline typename btree<P>::iterator
|
||||||
btree<P>::internal_insert(iterator iter, const value_type &v) {
|
btree<P>::internal_insert_common(iterator iter) {
|
||||||
if (!iter.node->leaf()) {
|
if (!iter.node->leaf()) {
|
||||||
// We can't insert on an internal node. Instead, we'll insert after the
|
// We can't insert on an internal node. Instead, we'll insert after the
|
||||||
// previous value which is guaranteed to be on a leaf node.
|
// previous value which is guaranteed to be on a leaf node.
|
||||||
@@ -2227,7 +2260,14 @@ btree<P>::internal_insert(iterator iter, const value_type &v) {
|
|||||||
} else if (!root()->leaf()) {
|
} else if (!root()->leaf()) {
|
||||||
++*mutable_size();
|
++*mutable_size();
|
||||||
}
|
}
|
||||||
iter.node->insert_value(iter.position, v);
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P> template <typename... Args>
|
||||||
|
inline typename btree<P>::iterator
|
||||||
|
btree<P>::internal_insert(iterator iter, Args&&... args) {
|
||||||
|
iter = internal_insert_common(iter);
|
||||||
|
iter.node->insert_value(iter.position, std::forward<Args>(args)...);
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src/3rdparty/cpp-btree/btree_container.h
vendored
29
src/3rdparty/cpp-btree/btree_container.h
vendored
@@ -201,9 +201,15 @@ class btree_unique_container : public btree_container<Tree> {
|
|||||||
std::pair<iterator,bool> insert(const value_type &x) {
|
std::pair<iterator,bool> insert(const value_type &x) {
|
||||||
return this->tree_.insert_unique(x);
|
return this->tree_.insert_unique(x);
|
||||||
}
|
}
|
||||||
|
std::pair<iterator,bool> insert(value_type &&x) {
|
||||||
|
return this->tree_.insert_unique(std::move(x));
|
||||||
|
}
|
||||||
iterator insert(iterator position, const value_type &x) {
|
iterator insert(iterator position, const value_type &x) {
|
||||||
return this->tree_.insert_unique(position, x);
|
return this->tree_.insert_unique(position, x);
|
||||||
}
|
}
|
||||||
|
iterator insert(iterator position, value_type &&x) {
|
||||||
|
return this->tree_.insert_unique(position, std::move(x));
|
||||||
|
}
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
void insert(InputIterator b, InputIterator e) {
|
void insert(InputIterator b, InputIterator e) {
|
||||||
this->tree_.insert_unique(b, e);
|
this->tree_.insert_unique(b, e);
|
||||||
@@ -238,21 +244,6 @@ class btree_map_container : public btree_unique_container<Tree> {
|
|||||||
typedef typename Tree::key_compare key_compare;
|
typedef typename Tree::key_compare key_compare;
|
||||||
typedef typename Tree::allocator_type allocator_type;
|
typedef typename Tree::allocator_type allocator_type;
|
||||||
|
|
||||||
private:
|
|
||||||
// A pointer-like object which only generates its value when
|
|
||||||
// dereferenced. Used by operator[] to avoid constructing an empty data_type
|
|
||||||
// if the key already exists in the map.
|
|
||||||
struct generate_value {
|
|
||||||
generate_value(const key_type &k)
|
|
||||||
: key(k) {
|
|
||||||
}
|
|
||||||
value_type operator*() const {
|
|
||||||
return std::make_pair(key, data_type());
|
|
||||||
}
|
|
||||||
const key_type &key;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Default constructor.
|
// Default constructor.
|
||||||
btree_map_container(const key_compare &comp = key_compare(),
|
btree_map_container(const key_compare &comp = key_compare(),
|
||||||
const allocator_type &alloc = allocator_type())
|
const allocator_type &alloc = allocator_type())
|
||||||
@@ -274,7 +265,7 @@ class btree_map_container : public btree_unique_container<Tree> {
|
|||||||
|
|
||||||
// Insertion routines.
|
// Insertion routines.
|
||||||
data_type& operator[](const key_type &key) {
|
data_type& operator[](const key_type &key) {
|
||||||
return this->tree_.insert_unique(key, generate_value(key)).first->second;
|
return this->tree_.insert_unique_args(key, std::piecewise_construct, std::forward_as_tuple(key), std::make_tuple()).first->second;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -329,9 +320,15 @@ class btree_multi_container : public btree_container<Tree> {
|
|||||||
iterator insert(const value_type &x) {
|
iterator insert(const value_type &x) {
|
||||||
return this->tree_.insert_multi(x);
|
return this->tree_.insert_multi(x);
|
||||||
}
|
}
|
||||||
|
iterator insert(value_type &&x) {
|
||||||
|
return this->tree_.insert_multi(std::move(x));
|
||||||
|
}
|
||||||
iterator insert(iterator position, const value_type &x) {
|
iterator insert(iterator position, const value_type &x) {
|
||||||
return this->tree_.insert_multi(position, x);
|
return this->tree_.insert_multi(position, x);
|
||||||
}
|
}
|
||||||
|
iterator insert(iterator position, value_type &&x) {
|
||||||
|
return this->tree_.insert_multi(position, std::move(x));
|
||||||
|
}
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
void insert(InputIterator b, InputIterator e) {
|
void insert(InputIterator b, InputIterator e) {
|
||||||
this->tree_.insert_multi(b, e);
|
this->tree_.insert_multi(b, e);
|
||||||
|
54
src/3rdparty/cpp-btree/safe_btree.h
vendored
54
src/3rdparty/cpp-btree/safe_btree.h
vendored
@@ -274,36 +274,64 @@ class safe_btree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insertion routines.
|
// Insertion routines.
|
||||||
template <typename ValuePointer>
|
template <typename... Args>
|
||||||
std::pair<iterator, bool> insert_unique(const key_type &key, ValuePointer value) {
|
std::pair<iterator,bool> insert_unique_args(const key_type &key, Args&&... args) {
|
||||||
std::pair<tree_iterator, bool> p = tree_.insert_unique(key, value);
|
std::pair<tree_iterator, bool> p = tree_.insert_unique_args(key, std::forward<Args>(args)...);
|
||||||
generation_ += p.second;
|
generation_ += p.second;
|
||||||
return std::make_pair(iterator(this, p.first), p.second);
|
return std::make_pair(iterator(this, p.first), p.second);
|
||||||
}
|
}
|
||||||
std::pair<iterator, bool> insert_unique(const value_type &v) {
|
std::pair<iterator,bool> insert_unique(const value_type &v) {
|
||||||
std::pair<tree_iterator, bool> p = tree_.insert_unique(v);
|
return insert_unique_args(params_type::key(v), v);
|
||||||
generation_ += p.second;
|
|
||||||
return std::make_pair(iterator(this, p.first), p.second);
|
|
||||||
}
|
}
|
||||||
iterator insert_unique(iterator position, const value_type &v) {
|
std::pair<iterator,bool> insert_unique(value_type &&v) {
|
||||||
|
return insert_unique_args(params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator insert_unique_hint_args(iterator position, const key_type &key, Args&&... args) {
|
||||||
tree_iterator tree_pos = position.iter();
|
tree_iterator tree_pos = position.iter();
|
||||||
++generation_;
|
++generation_;
|
||||||
return iterator(this, tree_.insert_unique(tree_pos, v));
|
return iterator(this, tree_.insert_unique_hint_args(tree_pos, key, std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
iterator insert_unique(iterator position, const value_type &v) {
|
||||||
|
return insert_unique_hint_args(position, params_type::key(v), v);
|
||||||
|
}
|
||||||
|
iterator insert_unique(iterator position, value_type &&v) {
|
||||||
|
return insert_unique_hint_args(position, params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
void insert_unique(InputIterator b, InputIterator e) {
|
void insert_unique(InputIterator b, InputIterator e) {
|
||||||
for (; b != e; ++b) {
|
for (; b != e; ++b) {
|
||||||
insert_unique(*b);
|
insert_unique(*b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator insert_multi(const value_type &v) {
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator insert_multi_args(const key_type &key, Args&&... args) {
|
||||||
++generation_;
|
++generation_;
|
||||||
return iterator(this, tree_.insert_multi(v));
|
return iterator(this, tree_.insert_multi_args(key, std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
iterator insert_multi(iterator position, const value_type &v) {
|
|
||||||
|
iterator insert_multi(const value_type &v) {
|
||||||
|
return insert_multi_args(params_type::key(v), v);
|
||||||
|
}
|
||||||
|
iterator insert_multi(value_type &&v) {
|
||||||
|
return insert_multi_args(params_type::key(v), std::move(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
iterator insert_multi_hint_args(iterator position, const key_type &key, Args&&... args) {
|
||||||
tree_iterator tree_pos = position.iter();
|
tree_iterator tree_pos = position.iter();
|
||||||
++generation_;
|
++generation_;
|
||||||
return iterator(this, tree_.insert_multi(tree_pos, v));
|
return iterator(this, tree_.insert_multi_hint_args(tree_pos, key, std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator insert_multi(iterator position, const value_type &v) {
|
||||||
|
return insert_multi_hint_args(position, params_type::key(v), v);
|
||||||
|
}
|
||||||
|
iterator insert_multi(iterator position, value_type &&v) {
|
||||||
|
return insert_multi_hint_args(position, params_type::key(v), std::move(v));
|
||||||
}
|
}
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
void insert_multi(InputIterator b, InputIterator e) {
|
void insert_multi(InputIterator b, InputIterator e) {
|
||||||
|
Reference in New Issue
Block a user