mirror of
https://github.com/boostorg/container.git
synced 2026-01-19 04:02:17 +00:00
Implement C++26 heterogeneous "insert" for set and flat_set. Range insertion functions in flat_tree are renamed to support some older compilers that have problems with SFINAE against the heterogeneous insert overload
This commit is contained in:
@@ -885,6 +885,18 @@ class flat_tree
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class Convertible>
|
||||
std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(Convertible) val)
|
||||
{
|
||||
std::pair<iterator,bool> ret;
|
||||
insert_commit_data data;
|
||||
ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
|
||||
ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
|
||||
: this->begin() + (data.position - this->cbegin());
|
||||
//: iterator(vector_iterator_get_ptr(data.position));
|
||||
return ret;
|
||||
}
|
||||
|
||||
iterator insert_equal(const value_type& val)
|
||||
{
|
||||
iterator i = this->upper_bound(KeyOfValue()(val));
|
||||
@@ -919,6 +931,21 @@ class flat_tree
|
||||
//: iterator(vector_iterator_get_ptr(data.position));
|
||||
}
|
||||
|
||||
template<class K>
|
||||
inline typename dtl::enable_if_c<
|
||||
!dtl::is_convertible<K, iterator>::value && //not convertible to iterator
|
||||
!dtl::is_convertible<K, const_iterator>::value //not convertible to const_iterator
|
||||
, iterator>::type
|
||||
insert_unique(const_iterator hint, BOOST_FWD_REF(K) val)
|
||||
{
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(hint));
|
||||
insert_commit_data data;
|
||||
return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
|
||||
? this->priv_insert_commit(data, boost::move(val))
|
||||
: this->begin() + (data.position - this->cbegin());
|
||||
//: iterator(vector_iterator_get_ptr(data.position));
|
||||
}
|
||||
|
||||
iterator insert_equal(const_iterator hint, const value_type& val)
|
||||
{
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(hint));
|
||||
@@ -936,7 +963,7 @@ class flat_tree
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_unique(InIt first, InIt last)
|
||||
void insert_unique_range(InIt first, InIt last)
|
||||
{
|
||||
dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
|
||||
container_type &seq = this->m_data.m_seq;
|
||||
@@ -963,7 +990,7 @@ class flat_tree
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_equal(InIt first, InIt last)
|
||||
void insert_equal_range(InIt first, InIt last)
|
||||
{
|
||||
if (first != last) {
|
||||
dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
|
||||
@@ -977,7 +1004,7 @@ class flat_tree
|
||||
//Ordered
|
||||
|
||||
template <class InIt>
|
||||
void insert_equal(ordered_range_t, InIt first, InIt last)
|
||||
void insert_equal_range(ordered_range_t, InIt first, InIt last)
|
||||
{
|
||||
const bool value = boost::container::dtl::
|
||||
has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
|
||||
@@ -985,7 +1012,7 @@ class flat_tree
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_unique(ordered_unique_range_t, InIt first, InIt last)
|
||||
void insert_unique_range(ordered_unique_range_t, InIt first, InIt last)
|
||||
{
|
||||
const bool value = boost::container::dtl::
|
||||
has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
|
||||
@@ -1331,15 +1358,15 @@ class flat_tree
|
||||
template<class C2>
|
||||
inline void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
|
||||
{
|
||||
this->insert_unique( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end()));
|
||||
this->insert_unique_range( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end()));
|
||||
}
|
||||
|
||||
template<class C2>
|
||||
inline void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
|
||||
{
|
||||
this->insert_equal( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end()));
|
||||
this->insert_equal_range( boost::make_move_iterator(source.begin())
|
||||
, boost::make_move_iterator(source.end()));
|
||||
}
|
||||
|
||||
inline void merge_unique(flat_tree& source)
|
||||
@@ -1541,10 +1568,10 @@ class flat_tree
|
||||
//for the constructor
|
||||
//Call end() every iteration as reallocation might have invalidated iterators
|
||||
if(unique_insertion){
|
||||
this->insert_unique(first, last);
|
||||
this->insert_unique_range(first, last);
|
||||
}
|
||||
else{
|
||||
this->insert_equal (first, last);
|
||||
this->insert_equal_range(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1645,7 +1672,7 @@ class flat_tree
|
||||
inline iterator priv_insert_commit
|
||||
(insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
|
||||
{
|
||||
return this->m_data.m_seq.insert
|
||||
return this->m_data.m_seq.emplace
|
||||
( commit_data.position
|
||||
, boost::forward<Convertible>(convertible));
|
||||
}
|
||||
|
||||
@@ -813,25 +813,27 @@ class tree
|
||||
&& boost::container::dtl::is_nothrow_swappable<Compare>::value )
|
||||
{ AllocHolder::swap(x); }
|
||||
|
||||
public:
|
||||
protected:
|
||||
|
||||
typedef typename Icont::insert_commit_data insert_commit_data;
|
||||
|
||||
// insert/erase
|
||||
template <class Comparable>
|
||||
std::pair<iterator,bool> insert_unique_check
|
||||
(const key_type& key, insert_commit_data &data)
|
||||
(const Comparable& key, insert_commit_data &data)
|
||||
{
|
||||
std::pair<iiterator, bool> ret =
|
||||
this->icont().insert_unique_check(key, data);
|
||||
this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data);
|
||||
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
|
||||
}
|
||||
|
||||
template <class Comparable>
|
||||
std::pair<iterator,bool> insert_unique_check
|
||||
(const_iterator hint, const key_type& key, insert_commit_data &data)
|
||||
(const_iterator hint, const Comparable& key, insert_commit_data &data)
|
||||
{
|
||||
BOOST_ASSERT((priv_is_linked)(hint));
|
||||
std::pair<iiterator, bool> ret =
|
||||
this->icont().insert_unique_check(hint.get(), key, data);
|
||||
this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data);
|
||||
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
|
||||
}
|
||||
|
||||
@@ -850,8 +852,9 @@ class tree
|
||||
std::pair<iterator,bool> insert_unique_convertible(BOOST_FWD_REF(MovableConvertible) v)
|
||||
{
|
||||
insert_commit_data data;
|
||||
const typename remove_cvref<MovableConvertible>::type & k = v; //Support emulated rvalue references
|
||||
std::pair<iterator,bool> ret =
|
||||
this->insert_unique_check(key_of_value_t()(v), data);
|
||||
this->insert_unique_check(key_of_value_t()(k), data);
|
||||
if(ret.second){
|
||||
ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
|
||||
}
|
||||
|
||||
@@ -1396,7 +1396,7 @@ class flat_map
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(InputIterator first, InputIterator last)
|
||||
{ m_flat_tree.insert_unique(first, last); }
|
||||
{ m_flat_tree.insert_unique_range(first, last); }
|
||||
|
||||
//! <b>Requires</b>: first, last are not iterators into *this.
|
||||
//!
|
||||
@@ -1414,7 +1414,7 @@ class flat_map
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
template <class InputIterator>
|
||||
inline void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
|
||||
{ m_flat_tree.insert_unique(ordered_unique_range, first, last); }
|
||||
{ m_flat_tree.insert_unique_range(ordered_unique_range, first, last); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
||||
@@ -1425,8 +1425,8 @@ class flat_map
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
inline void insert(std::initializer_list<value_type> il)
|
||||
{
|
||||
m_flat_tree.insert_unique( dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
m_flat_tree.insert_unique_range( dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
|
||||
@@ -1443,9 +1443,9 @@ class flat_map
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
inline void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
|
||||
{
|
||||
m_flat_tree.insert_unique(ordered_unique_range
|
||||
, dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
m_flat_tree.insert_unique_range(ordered_unique_range
|
||||
, dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2794,7 +2794,7 @@ class flat_multimap
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(InputIterator first, InputIterator last)
|
||||
{ m_flat_tree.insert_equal(first, last); }
|
||||
{ m_flat_tree.insert_equal_range(first, last); }
|
||||
|
||||
//! <b>Requires</b>: first, last are not iterators into *this.
|
||||
//!
|
||||
@@ -2811,7 +2811,7 @@ class flat_multimap
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
template <class InputIterator>
|
||||
inline void insert(ordered_range_t, InputIterator first, InputIterator last)
|
||||
{ m_flat_tree.insert_equal(ordered_range, first, last); }
|
||||
{ m_flat_tree.insert_equal_range(ordered_range, first, last); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
|
||||
@@ -2821,8 +2821,8 @@ class flat_multimap
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
inline void insert(std::initializer_list<value_type> il)
|
||||
{
|
||||
m_flat_tree.insert_equal( dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
m_flat_tree.insert_equal_range( dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
|
||||
@@ -2838,9 +2838,9 @@ class flat_multimap
|
||||
//! <b>Note</b>: Non-standard extension.
|
||||
inline void insert(ordered_range_t, std::initializer_list<value_type> il)
|
||||
{
|
||||
m_flat_tree.insert_equal( ordered_range
|
||||
, dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
m_flat_tree.insert_equal_range( ordered_range
|
||||
, dtl::force<impl_initializer_list>(il).begin()
|
||||
, dtl::force<impl_initializer_list>(il).end());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ class flat_set
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
|
||||
//! with key equivalent to the key of x.
|
||||
//!
|
||||
@@ -650,7 +650,8 @@ class flat_set
|
||||
//! to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
std::pair<iterator, bool> insert(const value_type &x);
|
||||
std::pair<iterator, bool> insert(const value_type &x)
|
||||
{ return this->tree_t::insert_unique(x); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
|
||||
//! only if there is no element in the container with key equivalent to the key of x.
|
||||
@@ -663,15 +664,35 @@ class flat_set
|
||||
//! to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
std::pair<iterator, bool> insert(value_type &&x);
|
||||
#else
|
||||
private:
|
||||
typedef std::pair<iterator, bool> insert_return_pair;
|
||||
public:
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique)
|
||||
#endif
|
||||
std::pair<iterator, bool> insert(value_type &&x)
|
||||
{ return this->tree_t::insert_unique(boost::move(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
|
||||
//! only if there is no element in the container with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only
|
||||
//! if the insertion takes place, and the iterator component of the pair
|
||||
//! points to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic search time plus linear insertion
|
||||
//! to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
(std::pair<iterator BOOST_MOVE_I bool>
|
||||
, typename dtl::enable_if_c<
|
||||
dtl::is_transparent<key_compare>::value && //transparent
|
||||
!dtl::is_convertible<K BOOST_MOVE_I iterator>::value && //not convertible to iterator
|
||||
!dtl::is_convertible<K BOOST_MOVE_I const_iterator>::value //not convertible to const_iterator
|
||||
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool>
|
||||
>::type)
|
||||
insert(K &&x)
|
||||
{ return this->tree_t::insert_unique(boost::forward<K>(x)); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -683,9 +704,11 @@ class flat_set
|
||||
//! right before p) plus insertion linear to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
iterator insert(const_iterator p, const value_type &x);
|
||||
iterator insert(const_iterator p, const value_type &x)
|
||||
{ return this->tree_t::insert_unique(p, x); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
|
||||
//! <b>Effects</b>: Move-inserts x in the container if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
|
||||
@@ -694,8 +717,38 @@ class flat_set
|
||||
//! right before p) plus insertion linear to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
iterator insert(const_iterator p, value_type &&x);
|
||||
iterator insert(const_iterator p, value_type &&x)
|
||||
{ return this->tree_t::insert_unique(p, boost::move(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Forward-inserts x in the container if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
|
||||
//! to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
|
||||
//! right before p) plus insertion linear to the elements with bigger keys than x.
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_transparent< key_compare
|
||||
BOOST_MOVE_I K
|
||||
BOOST_MOVE_I iterator
|
||||
>::type) //transparent
|
||||
insert(const_iterator p, K &&x)
|
||||
{ return this->tree_t::insert_unique(p, boost::forward<K>(x)); }
|
||||
|
||||
#else
|
||||
private:
|
||||
typedef std::pair<iterator, bool> insert_return_pair;
|
||||
public:
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique)
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_unique, const_iterator, const_iterator)
|
||||
#endif
|
||||
|
||||
@@ -709,7 +762,7 @@ class flat_set
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(InputIterator first, InputIterator last)
|
||||
{ this->tree_t::insert_unique(first, last); }
|
||||
{ this->tree_t::insert_unique_range(first, last); }
|
||||
|
||||
//! <b>Requires</b>: first, last are not iterators into *this and
|
||||
//! must be ordered according to the predicate and must be
|
||||
@@ -723,7 +776,7 @@ class flat_set
|
||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
|
||||
{ this->tree_t::insert_unique(ordered_unique_range, first, last); }
|
||||
{ this->tree_t::insert_unique_range(ordered_unique_range, first, last); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
|
||||
@@ -733,7 +786,7 @@ class flat_set
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
inline void insert(std::initializer_list<value_type> il)
|
||||
{ this->tree_t::insert_unique(il.begin(), il.end()); }
|
||||
{ this->tree_t::insert_unique_range(il.begin(), il.end()); }
|
||||
|
||||
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
|
||||
//! and must be unique values.
|
||||
@@ -745,7 +798,7 @@ class flat_set
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||
inline void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
|
||||
{ this->tree_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
|
||||
{ this->tree_t::insert_unique_range(ordered_unique_range, il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
|
||||
@@ -1678,7 +1731,7 @@ class flat_multiset
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(InputIterator first, InputIterator last)
|
||||
{ this->tree_t::insert_equal(first, last); }
|
||||
{ this->tree_t::insert_equal_range(first, last); }
|
||||
|
||||
//! <b>Requires</b>: first, last are not iterators into *this and
|
||||
//! must be ordered according to the predicate.
|
||||
@@ -1691,7 +1744,7 @@ class flat_multiset
|
||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||
template <class InputIterator>
|
||||
inline void insert(ordered_range_t, InputIterator first, InputIterator last)
|
||||
{ this->tree_t::insert_equal(ordered_range, first, last); }
|
||||
{ this->tree_t::insert_equal_range(ordered_range, first, last); }
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
|
||||
@@ -1700,7 +1753,7 @@ class flat_multiset
|
||||
//!
|
||||
//! <b>Note</b>: If an element is inserted it might invalidate elements.
|
||||
inline void insert(std::initializer_list<value_type> il)
|
||||
{ this->tree_t::insert_equal(il.begin(), il.end()); }
|
||||
{ this->tree_t::insert_equal_range(il.begin(), il.end()); }
|
||||
|
||||
//! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate.
|
||||
//!
|
||||
@@ -1711,7 +1764,7 @@ class flat_multiset
|
||||
//!
|
||||
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
|
||||
inline void insert(ordered_range_t, std::initializer_list<value_type> il)
|
||||
{ this->tree_t::insert_equal(ordered_range, il.begin(), il.end()); }
|
||||
{ this->tree_t::insert_equal_range(ordered_range, il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
|
||||
|
||||
@@ -574,7 +574,7 @@ class set
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
|
||||
//! with key equivalent to the key of x.
|
||||
//!
|
||||
@@ -583,7 +583,8 @@ class set
|
||||
//! points to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
std::pair<iterator, bool> insert(const value_type &x);
|
||||
std::pair<iterator, bool> insert(const value_type &x)
|
||||
{ return this->base_t::insert_unique_convertible(x); }
|
||||
|
||||
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
@@ -593,16 +594,32 @@ class set
|
||||
//! points to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
std::pair<iterator, bool> insert(value_type &&x);
|
||||
#else
|
||||
private:
|
||||
typedef std::pair<iterator, bool> insert_return_pair;
|
||||
public:
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH
|
||||
(insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible)
|
||||
#endif
|
||||
std::pair<iterator, bool> insert(value_type &&x)
|
||||
{ return this->base_t::insert_unique_convertible(boost::move(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Forward constructs a new value from x if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only
|
||||
//! if the insertion takes place, and the iterator component of the pair
|
||||
//! points to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
(std::pair<iterator BOOST_MOVE_I bool>
|
||||
, typename dtl::enable_if_c<
|
||||
dtl::is_transparent<key_compare>::value && //transparent
|
||||
!dtl::is_convertible<K BOOST_MOVE_I iterator>::value && //not convertible to iterator
|
||||
!dtl::is_convertible<K BOOST_MOVE_I const_iterator>::value //not convertible to const_iterator
|
||||
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool>
|
||||
>::type)
|
||||
insert(K &&x)
|
||||
{ return this->base_t::insert_unique_convertible(boost::forward<K>(x)); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -612,7 +629,8 @@ class set
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
iterator insert(const_iterator p, const value_type &x);
|
||||
iterator insert(const_iterator p, const value_type &x)
|
||||
{ return this->base_t::insert_unique_hint_convertible(p, x); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -620,8 +638,38 @@ class set
|
||||
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
iterator insert(const_iterator p, value_type &&x);
|
||||
iterator insert(const_iterator p, value_type &&x)
|
||||
{ return this->base_t::insert_unique_hint_convertible(p, boost::move(x)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Requires</b>: This overload is available only if
|
||||
//! key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: Inserts an element forward constructed from x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
//!
|
||||
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class K>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_transparent< key_compare
|
||||
BOOST_MOVE_I K
|
||||
BOOST_MOVE_I iterator
|
||||
>::type) //transparent
|
||||
insert(const_iterator p, K &&x)
|
||||
{ return this->base_t::insert_unique_hint_convertible(p, boost::forward<K>(x)); }
|
||||
|
||||
#else
|
||||
private:
|
||||
typedef std::pair<iterator, bool> insert_return_pair;
|
||||
public:
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH
|
||||
(insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible)
|
||||
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
|
||||
(insert, value_type, iterator, this->base_t::insert_unique_hint_convertible, const_iterator, const_iterator)
|
||||
#endif
|
||||
|
||||
@@ -495,104 +495,6 @@ bool flat_tree_extract_adopt_test()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef flat_set<int, test::less_transparent> set_t;
|
||||
typedef flat_multiset<int, test::less_transparent> mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
|
||||
const set_t &cset1 = set1;
|
||||
const mset_t &cmset1 = mset1;
|
||||
|
||||
set1.insert(1);
|
||||
set1.insert(1);
|
||||
set1.insert(2);
|
||||
set1.insert(2);
|
||||
set1.insert(3);
|
||||
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
mset1.insert(2);
|
||||
mset1.insert(2);
|
||||
mset1.insert(3);
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(*set1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.find(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(set1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cset1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mset1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmset1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!set1.contains(find_me))
|
||||
return false;
|
||||
if(!cset1.contains(find_me))
|
||||
return false;
|
||||
if(!mset1.contains(find_me))
|
||||
return false;
|
||||
if(!cmset1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(*set1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(*set1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*mset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cmset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(*set1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
if(*mset1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cmset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (set1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (set1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// An ordered sequence of std:pair is also ordered by std::pair::first.
|
||||
struct with_lookup_by_first
|
||||
{
|
||||
@@ -765,9 +667,16 @@ int main()
|
||||
if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >())
|
||||
return 1;
|
||||
|
||||
if(!test_heterogeneous_lookups()){
|
||||
if (!test::test_heterogeneous_lookup
|
||||
< flat_set<int, less_transparent>
|
||||
, flat_multiset<int, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
if (!test::test_heterogeneous_insert
|
||||
< flat_set<test::movable_int, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!test_heterogeneous_lookup_by_partial_key()){
|
||||
return 1;
|
||||
|
||||
@@ -189,6 +189,33 @@ bool node_type_test()
|
||||
if(dst.size() != 5)
|
||||
return false;
|
||||
}
|
||||
{
|
||||
typedef set<test::movable_int, test::less_transparent> set_t;
|
||||
typedef multiset<test::movable_int, test::less_transparent> mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
//extract
|
||||
const test::non_copymovable_int extract_me(1);
|
||||
|
||||
set1.insert(1);
|
||||
mset1.emplace(1);
|
||||
mset1.emplace(1);
|
||||
|
||||
//extract
|
||||
if (!set1.extract(1))
|
||||
return false;
|
||||
if (set1.extract(1))
|
||||
return false;
|
||||
|
||||
if (!mset1.extract(1))
|
||||
return false;
|
||||
if (!mset1.extract(1))
|
||||
return false;
|
||||
if (mset1.extract(1))
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -352,127 +379,9 @@ void test_merge_from_different_comparison()
|
||||
set1.merge(set2);
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef set<int, test::less_transparent> set_t;
|
||||
typedef multiset<int, test::less_transparent> mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
|
||||
const set_t &cset1 = set1;
|
||||
const mset_t &cmset1 = mset1;
|
||||
|
||||
set1.insert(1);
|
||||
set1.insert(1);
|
||||
set1.insert(2);
|
||||
set1.insert(2);
|
||||
set1.insert(3);
|
||||
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
mset1.insert(2);
|
||||
mset1.insert(2);
|
||||
mset1.insert(3);
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(*set1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.find(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(set1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cset1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mset1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmset1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!set1.contains(find_me))
|
||||
return false;
|
||||
if(!cset1.contains(find_me))
|
||||
return false;
|
||||
if(!mset1.contains(find_me))
|
||||
return false;
|
||||
if(!cmset1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(*set1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(*set1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*mset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cmset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(*set1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
if(*mset1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cmset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (set1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (set1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 0)
|
||||
return false;
|
||||
|
||||
//extract
|
||||
set1.clear();
|
||||
set1.insert(1);
|
||||
mset1.clear();
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
|
||||
const test::non_copymovable_int extract_me(1);
|
||||
|
||||
if (!set1.extract(extract_me))
|
||||
return false;
|
||||
if (set1.extract(extract_me))
|
||||
return false;
|
||||
|
||||
if (!mset1.extract(extract_me))
|
||||
return false;
|
||||
if (!mset1.extract(extract_me))
|
||||
return false;
|
||||
if (mset1.extract(extract_me))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
using namespace boost::container::test;
|
||||
//Recursive container instantiation
|
||||
{
|
||||
set<recursive_set> set_;
|
||||
@@ -509,7 +418,15 @@ int main ()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!test_heterogeneous_lookups())
|
||||
if (!test::test_heterogeneous_lookup
|
||||
< set<int, less_transparent>
|
||||
, multiset<int, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
if (!test::test_heterogeneous_insert
|
||||
< set<test::movable_int, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
@@ -1002,6 +1002,146 @@ bool instantiate_constructors()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename IntSetType, typename IntMultisetType>
|
||||
bool test_heterogeneous_lookup()
|
||||
{
|
||||
typedef IntSetType set_t;
|
||||
typedef IntMultisetType mset_t;
|
||||
|
||||
set_t set1;
|
||||
mset_t mset1;
|
||||
|
||||
const set_t &cset1 = set1;
|
||||
const mset_t &cmset1 = mset1;
|
||||
|
||||
set1.insert(1);
|
||||
set1.insert(1);
|
||||
set1.insert(2);
|
||||
set1.insert(2);
|
||||
set1.insert(3);
|
||||
|
||||
mset1.insert(1);
|
||||
mset1.insert(1);
|
||||
mset1.insert(2);
|
||||
mset1.insert(2);
|
||||
mset1.insert(3);
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(*set1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.find(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.find(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(set1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cset1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mset1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmset1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!set1.contains(find_me))
|
||||
return false;
|
||||
if(!cset1.contains(find_me))
|
||||
return false;
|
||||
if(!mset1.contains(find_me))
|
||||
return false;
|
||||
if(!cmset1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(*set1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*mset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
if(*cmset1.lower_bound(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(*set1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*mset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
if(*cmset1.upper_bound(find_me) != 3)
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(*set1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
if(*mset1.equal_range(find_me).first != 2)
|
||||
return false;
|
||||
if(*cmset1.equal_range(find_me).second != 3)
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (set1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (set1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mset1.erase(find_me) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename MovableIntSetType>
|
||||
bool test_heterogeneous_insert()
|
||||
{
|
||||
typedef MovableIntSetType set_t;
|
||||
|
||||
set_t set1;
|
||||
const set_t &cset1 = set1;
|
||||
|
||||
//insert
|
||||
if(!set1.insert(1).second)
|
||||
return false;
|
||||
if (cset1.find(1) == cset1.end())
|
||||
return false;
|
||||
if(set1.insert(1).second)
|
||||
return false;
|
||||
if (cset1.find(1) == cset1.end())
|
||||
return false;
|
||||
|
||||
//insert with hint
|
||||
if(set1.find(2) != set1.end())
|
||||
return false;
|
||||
typename set_t::iterator i = set1.insert(set1.begin(), 2);
|
||||
if(i != set1.insert(set1.end(), 2))
|
||||
return false;
|
||||
if (cset1.find(2) == cset1.end())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} //namespace test{
|
||||
} //namespace container {
|
||||
} //namespace boost{
|
||||
|
||||
Reference in New Issue
Block a user