Skip to content

Commit e4f42d0

Browse files
committed
Implement heterogeneous "at()" operation for map/flat_map
1 parent 9f08ecc commit e4f42d0

File tree

3 files changed

+129
-1
lines changed

3 files changed

+129
-1
lines changed

include/boost/container/flat_map.hpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,12 +982,60 @@ class flat_map
982982
BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
983983
{
984984
const_iterator i = this->find(k);
985+
if(i == this->cend()){
986+
throw_out_of_range("flat_map::at key not found");
987+
}
988+
return i->second;
989+
}
990+
991+
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
992+
//!
993+
//! Returns: A reference to the element whose key is equivalent to x.
994+
//!
995+
//! Throws: An exception object of type out_of_range if no such element is present.
996+
//!
997+
//! Complexity: logarithmic.
998+
template<class K>
999+
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1000+
BOOST_CONTAINER_DOC1ST
1001+
( T&
1002+
, typename dtl::enable_if_transparent< key_compare
1003+
BOOST_MOVE_I K
1004+
BOOST_MOVE_I T&
1005+
>::type) //transparent
1006+
at(const K& k)
1007+
{
1008+
iterator i = this->find(k);
9851009
if(i == this->end()){
9861010
throw_out_of_range("flat_map::at key not found");
9871011
}
9881012
return i->second;
9891013
}
9901014

1015+
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
1016+
//!
1017+
//! Returns: A reference to the element whose key is equivalent to x.
1018+
//!
1019+
//! Throws: An exception object of type out_of_range if no such element is present.
1020+
//!
1021+
//! Complexity: logarithmic.
1022+
template<class K>
1023+
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
1024+
BOOST_CONTAINER_DOC1ST
1025+
( const T&
1026+
, typename dtl::enable_if_transparent< key_compare
1027+
BOOST_MOVE_I K
1028+
BOOST_MOVE_I const T&
1029+
>::type) //transparent
1030+
at(const K& k) const
1031+
{
1032+
const_iterator i = this->find(k);
1033+
if(i == this->cend()){
1034+
throw_out_of_range("flat_map::at key not found");
1035+
}
1036+
return i->second;
1037+
}
1038+
9911039
//////////////////////////////////////////////
9921040
//
9931041
// modifiers

include/boost/container/map.hpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class map
713713
//! <b>Returns</b>: A reference to the element whose key is equivalent to x.
714714
//! Throws: An exception object of type out_of_range if no such element is present.
715715
//! <b>Complexity</b>: logarithmic.
716-
T& at(const key_type& k)
716+
BOOST_CONTAINER_ATTRIBUTE_NODISCARD T& at(const key_type& k)
717717
{
718718
iterator i = this->find(k);
719719
if(i == this->end()){
@@ -728,12 +728,60 @@ class map
728728
BOOST_CONTAINER_ATTRIBUTE_NODISCARD const T& at(const key_type& k) const
729729
{
730730
const_iterator i = this->find(k);
731+
if(i == this->cend()){
732+
throw_out_of_range("map::at key not found");
733+
}
734+
return i->second;
735+
}
736+
737+
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
738+
//!
739+
//! Returns: A reference to the element whose key is equivalent to x.
740+
//!
741+
//! Throws: An exception object of type out_of_range if no such element is present.
742+
//!
743+
//! Complexity: logarithmic.
744+
template<class K>
745+
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
746+
BOOST_CONTAINER_DOC1ST
747+
( T&
748+
, typename dtl::enable_if_transparent< key_compare
749+
BOOST_MOVE_I K
750+
BOOST_MOVE_I T&
751+
>::type) //transparent
752+
at(const K& k)
753+
{
754+
iterator i = this->find(k);
731755
if(i == this->end()){
732756
throw_out_of_range("map::at key not found");
733757
}
734758
return i->second;
735759
}
736760

761+
//! <b>Precondition</b>: This overload is available only if key_compare::is_transparent exists.
762+
//!
763+
//! Returns: A reference to the element whose key is equivalent to x.
764+
//!
765+
//! Throws: An exception object of type out_of_range if no such element is present.
766+
//!
767+
//! Complexity: logarithmic.
768+
template<class K>
769+
BOOST_CONTAINER_ATTRIBUTE_NODISCARD
770+
BOOST_CONTAINER_DOC1ST
771+
( const T&
772+
, typename dtl::enable_if_transparent< key_compare
773+
BOOST_MOVE_I K
774+
BOOST_MOVE_I const T&
775+
>::type) //transparent
776+
at(const K& k) const
777+
{
778+
const_iterator i = this->find(k);
779+
if(i == this->cend()){
780+
throw_out_of_range("map::at key not found");
781+
}
782+
return i->second;
783+
}
784+
737785
//////////////////////////////////////////////
738786
//
739787
// modifiers

test/map_test.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,7 @@ bool test_heterogeneous_lookup()
15751575
mmap1.insert(value_type(3, 'e'));
15761576

15771577
const test::non_copymovable_int find_me(2);
1578+
const test::non_copymovable_int not_present(5);
15781579

15791580
//find
15801581
if(map1.find(find_me)->second != 'd')
@@ -1585,6 +1586,15 @@ bool test_heterogeneous_lookup()
15851586
return false;
15861587
if(cmmap1.find(find_me)->second != 'c')
15871588
return false;
1589+
if(map1.find(not_present) != map1.end())
1590+
return false;
1591+
if(cmap1.find(not_present) != cmap1.end())
1592+
return false;
1593+
if(mmap1.find(not_present) != mmap1.end())
1594+
return false;
1595+
if(cmmap1.find(not_present) != mmap1.cend())
1596+
return false;
1597+
15881598

15891599
//count
15901600
if(map1.count(find_me) != 1)
@@ -1595,6 +1605,14 @@ bool test_heterogeneous_lookup()
15951605
return false;
15961606
if(cmmap1.count(find_me) != 2)
15971607
return false;
1608+
if(map1.count(not_present) != 0)
1609+
return false;
1610+
if(cmap1.count(not_present) != 0)
1611+
return false;
1612+
if(mmap1.count(not_present) != 0)
1613+
return false;
1614+
if(cmmap1.count(not_present) != 0)
1615+
return false;
15981616

15991617
//contains
16001618
if(!map1.contains(find_me))
@@ -1605,6 +1623,20 @@ bool test_heterogeneous_lookup()
16051623
return false;
16061624
if(!cmmap1.contains(find_me))
16071625
return false;
1626+
if(map1.contains(not_present))
1627+
return false;
1628+
if(cmap1.contains(not_present))
1629+
return false;
1630+
if(mmap1.contains(not_present))
1631+
return false;
1632+
if(cmmap1.contains(not_present))
1633+
return false;
1634+
1635+
//at
1636+
if(map1.at(find_me) != 'd')
1637+
return false;
1638+
if(cmap1.at(find_me) != 'd')
1639+
return false;
16081640

16091641
//lower_bound
16101642
if(map1.lower_bound(find_me)->second != 'd')

0 commit comments

Comments
 (0)