Implement heterogeneous "at()" operation for map/flat_map

This commit is contained in:
Ion Gaztañaga
2025-11-07 23:09:05 +01:00
parent 9f08eccc05
commit e4f42d03cb
3 changed files with 129 additions and 1 deletions

View File

@@ -982,12 +982,60 @@ class flat_map
BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
{
const_iterator i = this->find(k);
if(i == this->cend()){
throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
//!
//! Returns: 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.
//!
//! Complexity: logarithmic.
template<class K>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
BOOST_CONTAINER_DOC1ST
( T&
, typename dtl::enable_if_transparent< key_compare
BOOST_MOVE_I K
BOOST_MOVE_I T&
>::type) //transparent
at(const K& k)
{
iterator i = this->find(k);
if(i == this->end()){
throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
//!
//! Returns: 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.
//!
//! Complexity: logarithmic.
template<class K>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
BOOST_CONTAINER_DOC1ST
( const T&
, typename dtl::enable_if_transparent< key_compare
BOOST_MOVE_I K
BOOST_MOVE_I const T&
>::type) //transparent
at(const K& k) const
{
const_iterator i = this->find(k);
if(i == this->cend()){
throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
//////////////////////////////////////////////
//
// modifiers

View File

@@ -713,7 +713,7 @@ class map
//! <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.
T& at(const key_type& k)
BOOST_CONTAINER_ATTRIBUTE_NODISCARD T& at(const key_type& k)
{
iterator i = this->find(k);
if(i == this->end()){
@@ -728,12 +728,60 @@ class map
BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
{
const_iterator i = this->find(k);
if(i == this->cend()){
throw_out_of_range("map::at key not found");
}
return i->second;
}
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
//!
//! Returns: 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.
//!
//! Complexity: logarithmic.
template<class K>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
BOOST_CONTAINER_DOC1ST
( T&
, typename dtl::enable_if_transparent< key_compare
BOOST_MOVE_I K
BOOST_MOVE_I T&
>::type) //transparent
at(const K& k)
{
iterator i = this->find(k);
if(i == this->end()){
throw_out_of_range("map::at key not found");
}
return i->second;
}
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
//!
//! Returns: 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.
//!
//! Complexity: logarithmic.
template<class K>
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
BOOST_CONTAINER_DOC1ST
( const T&
, typename dtl::enable_if_transparent< key_compare
BOOST_MOVE_I K
BOOST_MOVE_I const T&
>::type) //transparent
at(const K& k) const
{
const_iterator i = this->find(k);
if(i == this->cend()){
throw_out_of_range("map::at key not found");
}
return i->second;
}
//////////////////////////////////////////////
//
// modifiers

View File

@@ -1575,6 +1575,7 @@ bool test_heterogeneous_lookup()
mmap1.insert(value_type(3, 'e'));
const test::non_copymovable_int find_me(2);
const test::non_copymovable_int not_present(5);
//find
if(map1.find(find_me)->second != 'd')
@@ -1585,6 +1586,15 @@ bool test_heterogeneous_lookup()
return false;
if(cmmap1.find(find_me)->second != 'c')
return false;
if(map1.find(not_present) != map1.end())
return false;
if(cmap1.find(not_present) != cmap1.end())
return false;
if(mmap1.find(not_present) != mmap1.end())
return false;
if(cmmap1.find(not_present) != mmap1.cend())
return false;
//count
if(map1.count(find_me) != 1)
@@ -1595,6 +1605,14 @@ bool test_heterogeneous_lookup()
return false;
if(cmmap1.count(find_me) != 2)
return false;
if(map1.count(not_present) != 0)
return false;
if(cmap1.count(not_present) != 0)
return false;
if(mmap1.count(not_present) != 0)
return false;
if(cmmap1.count(not_present) != 0)
return false;
//contains
if(!map1.contains(find_me))
@@ -1605,6 +1623,20 @@ bool test_heterogeneous_lookup()
return false;
if(!cmmap1.contains(find_me))
return false;
if(map1.contains(not_present))
return false;
if(cmap1.contains(not_present))
return false;
if(mmap1.contains(not_present))
return false;
if(cmmap1.contains(not_present))
return false;
//at
if(map1.at(find_me) != 'd')
return false;
if(cmap1.at(find_me) != 'd')
return false;
//lower_bound
if(map1.lower_bound(find_me)->second != 'd')