mirror of
https://github.com/boostorg/container.git
synced 2026-01-19 04:02:17 +00:00
Implement transparent insert_or_assign (C++26) for map.
This commit is contained in:
@@ -1115,10 +1115,10 @@ class tree
|
||||
std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
|
||||
{
|
||||
insert_commit_data data;
|
||||
const key_type & k = key; //Support emulated rvalue references
|
||||
const typename remove_cvref<KeyType>::type & k = key; //Support emulated rvalue references
|
||||
std::pair<iiterator, bool> ret =
|
||||
hint == const_iterator() ? this->icont().insert_unique_check(k, data)
|
||||
: this->icont().insert_unique_check(hint.get(), k, data);
|
||||
hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data)
|
||||
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
|
||||
if(ret.second){
|
||||
ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
|
||||
}
|
||||
|
||||
@@ -611,6 +611,31 @@ class map
|
||||
inline std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::move(k), ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, move(obj)).
|
||||
//!
|
||||
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! took place. The iterator component is pointing at the element that was inserted or updated.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container.
|
||||
template <class K, class M>
|
||||
|
||||
BOOST_CONTAINER_DOC1ST
|
||||
( std::pair<iterator BOOST_MOVE_I bool>
|
||||
, typename dtl::enable_if_transparent< key_compare
|
||||
BOOST_MOVE_I K
|
||||
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool>
|
||||
>::type) //transparent
|
||||
insert_or_assign(BOOST_FWD_REF(K) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::forward<K>(k), ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
|
||||
@@ -645,6 +670,31 @@ class map
|
||||
inline iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)).first; }
|
||||
|
||||
//! <b>Requires</b>: This overload is available only if key_compare::is_transparent exists.
|
||||
//!
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, move(obj)) and the new element
|
||||
//! to the container as close as possible to the position just before hint.
|
||||
//!
|
||||
//! No iterators or references are invalidated. If the insertion is successful, pointers and references
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container in general, but amortized constant if
|
||||
//! the new element is inserted just before hint.
|
||||
template <class K, class M>
|
||||
BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_transparent< key_compare
|
||||
BOOST_MOVE_I K
|
||||
BOOST_MOVE_I iterator
|
||||
>::type) //transparent
|
||||
insert_or_assign(const_iterator hint, BOOST_FWD_REF(K) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(hint, ::boost::forward<K>(k), ::boost::forward<M>(obj)).first; }
|
||||
|
||||
//! <b>Returns</b>: A reference to the element whose key is equivalent to x.
|
||||
//! Throws: An exception object of type out_of_range if no such element is present.
|
||||
//! <b>Complexity</b>: logarithmic.
|
||||
|
||||
@@ -261,115 +261,135 @@ void test_merge_from_different_comparison()
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
typedef map<int, char, less_transparent> map_t;
|
||||
typedef multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
{
|
||||
typedef map<int, char, less_transparent> map_t;
|
||||
typedef multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
if(!map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
if(map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!map1.contains(find_me))
|
||||
return false;
|
||||
if(!cmap1.contains(find_me))
|
||||
return false;
|
||||
if(!mmap1.contains(find_me))
|
||||
return false;
|
||||
if(!cmmap1.contains(find_me))
|
||||
return false;
|
||||
//contains
|
||||
if(!map1.contains(find_me))
|
||||
return false;
|
||||
if(!cmap1.contains(find_me))
|
||||
return false;
|
||||
if(!mmap1.contains(find_me))
|
||||
return false;
|
||||
if(!cmmap1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (map1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (map1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 0)
|
||||
return false;
|
||||
//erase
|
||||
if (map1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (map1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 0)
|
||||
return false;
|
||||
}
|
||||
{
|
||||
typedef map<test::movable_int, char, less_transparent> map_t;
|
||||
|
||||
map_t map1;
|
||||
|
||||
//insert_or_assign
|
||||
if(!map1.insert_or_assign(1, 'e').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
|
||||
//insert_or_assign with hint
|
||||
if(map1.find(2) != map1.end())
|
||||
return false;
|
||||
map_t::iterator i = map1.insert_or_assign(map1.begin(), 2, 'e');
|
||||
if(i != map1.insert_or_assign(map1.end(), 2, 'b'))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user