Skip to content

Commit eef8948

Browse files
committed
[libc++] Refactor __tree::__find_equal to not have an out parameter
1 parent 0b3ee20 commit eef8948

File tree

2 files changed

+102
-127
lines changed

2 files changed

+102
-127
lines changed

libcxx/include/__tree

Lines changed: 98 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,15 +1086,89 @@ public:
10861086

10871087
// FIXME: Make this function const qualified. Unfortunately doing so
10881088
// breaks existing code which uses non-const callable comparators.
1089+
1090+
// Find place to insert if __v doesn't exist
1091+
// Set __parent to parent of null leaf
1092+
// Return reference to null leaf
1093+
// If __v exists, set parent to node of __v and return reference to node of __v
10891094
template <class _Key>
1090-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v);
1095+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) {
1096+
using _PairT = pair<__end_node_pointer, __node_base_pointer&>;
1097+
1098+
__node_pointer __node = __root();
1099+
1100+
if (__node == nullptr) {
1101+
auto __end = __end_node();
1102+
return _PairT(__end, __end->__left_);
1103+
}
1104+
1105+
__node_base_pointer* __node_ptr = __root_ptr();
1106+
while (true) {
1107+
if (value_comp()(__v, __node->__value_)) {
1108+
if (__node->__left_ == nullptr)
1109+
return _PairT(static_cast<__end_node_pointer>(__node), __node->__left_);
1110+
1111+
__node_ptr = std::addressof(__node->__left_);
1112+
__node = static_cast<__node_pointer>(__node->__left_);
1113+
} else if (value_comp()(__node->__value_, __v)) {
1114+
if (__node->__right_ == nullptr)
1115+
return _PairT(static_cast<__end_node_pointer>(__node), __node->__right_);
1116+
1117+
__node_ptr = std::addressof(__node->__right_);
1118+
__node = static_cast<__node_pointer>(__node->__right_);
1119+
} else {
1120+
return _PairT(static_cast<__end_node_pointer>(__node), *__node_ptr);
1121+
}
1122+
}
1123+
}
1124+
10911125
template <class _Key>
1092-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v) const {
1093-
return const_cast<__tree*>(this)->__find_equal(__parent, __v);
1126+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) const {
1127+
return const_cast<__tree*>(this)->__find_equal(__v);
10941128
}
1129+
1130+
// Find place to insert if __v doesn't exist
1131+
// First check prior to __hint.
1132+
// Next check after __hint.
1133+
// Next do O(log N) search.
1134+
// Set __parent to parent of null leaf
1135+
// Return reference to null leaf
1136+
// If __v exists, set parent to node of __v and return reference to node of __v
10951137
template <class _Key>
1096-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer&
1097-
__find_equal(const_iterator __hint, __end_node_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v);
1138+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&>
1139+
__find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v) {
1140+
using _PairT = pair<__end_node_pointer, __node_base_pointer&>;
1141+
1142+
if (__hint == end() || value_comp()(__v, *__hint)) { // check before
1143+
// __v < *__hint
1144+
const_iterator __prior = __hint;
1145+
if (__prior == begin() || value_comp()(*--__prior, __v)) {
1146+
// *prev(__hint) < __v < *__hint
1147+
if (__hint.__ptr_->__left_ == nullptr)
1148+
return _PairT(__hint.__ptr_, __hint.__ptr_->__left_);
1149+
return _PairT(__prior.__ptr_, static_cast<__node_pointer>(__prior.__ptr_)->__right_);
1150+
}
1151+
// __v <= *prev(__hint)
1152+
return __find_equal(__v);
1153+
}
1154+
1155+
if (value_comp()(*__hint, __v)) { // check after
1156+
// *__hint < __v
1157+
const_iterator __next = std::next(__hint);
1158+
if (__next == end() || value_comp()(__v, *__next)) {
1159+
// *__hint < __v < *std::next(__hint)
1160+
if (__hint.__get_np()->__right_ == nullptr)
1161+
return _PairT(__hint.__ptr_, static_cast<__node_pointer>(__hint.__ptr_)->__right_);
1162+
return _PairT(__next.__ptr_, __next.__ptr_->__left_);
1163+
}
1164+
// *next(__hint) <= __v
1165+
return __find_equal(__v);
1166+
}
1167+
1168+
// else __v == *__hint
1169+
__dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
1170+
return _PairT(__hint.__ptr_, __dummy);
1171+
}
10981172

10991173
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t) {
11001174
__copy_assign_alloc(__t, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
@@ -1647,94 +1721,6 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co
16471721
return __find_leaf_low(__parent, __v);
16481722
}
16491723

1650-
// Find place to insert if __v doesn't exist
1651-
// Set __parent to parent of null leaf
1652-
// Return reference to null leaf
1653-
// If __v exists, set parent to node of __v and return reference to node of __v
1654-
template <class _Tp, class _Compare, class _Allocator>
1655-
template <class _Key>
1656-
typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
1657-
__tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, const _Key& __v) {
1658-
__node_pointer __nd = __root();
1659-
__node_base_pointer* __nd_ptr = __root_ptr();
1660-
if (__nd != nullptr) {
1661-
while (true) {
1662-
if (value_comp()(__v, __nd->__value_)) {
1663-
if (__nd->__left_ != nullptr) {
1664-
__nd_ptr = std::addressof(__nd->__left_);
1665-
__nd = static_cast<__node_pointer>(__nd->__left_);
1666-
} else {
1667-
__parent = static_cast<__end_node_pointer>(__nd);
1668-
return __parent->__left_;
1669-
}
1670-
} else if (value_comp()(__nd->__value_, __v)) {
1671-
if (__nd->__right_ != nullptr) {
1672-
__nd_ptr = std::addressof(__nd->__right_);
1673-
__nd = static_cast<__node_pointer>(__nd->__right_);
1674-
} else {
1675-
__parent = static_cast<__end_node_pointer>(__nd);
1676-
return __nd->__right_;
1677-
}
1678-
} else {
1679-
__parent = static_cast<__end_node_pointer>(__nd);
1680-
return *__nd_ptr;
1681-
}
1682-
}
1683-
}
1684-
__parent = __end_node();
1685-
return __parent->__left_;
1686-
}
1687-
1688-
// Find place to insert if __v doesn't exist
1689-
// First check prior to __hint.
1690-
// Next check after __hint.
1691-
// Next do O(log N) search.
1692-
// Set __parent to parent of null leaf
1693-
// Return reference to null leaf
1694-
// If __v exists, set parent to node of __v and return reference to node of __v
1695-
template <class _Tp, class _Compare, class _Allocator>
1696-
template <class _Key>
1697-
typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal(
1698-
const_iterator __hint, __end_node_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v) {
1699-
if (__hint == end() || value_comp()(__v, *__hint)) // check before
1700-
{
1701-
// __v < *__hint
1702-
const_iterator __prior = __hint;
1703-
if (__prior == begin() || value_comp()(*--__prior, __v)) {
1704-
// *prev(__hint) < __v < *__hint
1705-
if (__hint.__ptr_->__left_ == nullptr) {
1706-
__parent = __hint.__ptr_;
1707-
return __parent->__left_;
1708-
} else {
1709-
__parent = __prior.__ptr_;
1710-
return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
1711-
}
1712-
}
1713-
// __v <= *prev(__hint)
1714-
return __find_equal(__parent, __v);
1715-
} else if (value_comp()(*__hint, __v)) // check after
1716-
{
1717-
// *__hint < __v
1718-
const_iterator __next = std::next(__hint);
1719-
if (__next == end() || value_comp()(__v, *__next)) {
1720-
// *__hint < __v < *std::next(__hint)
1721-
if (__hint.__get_np()->__right_ == nullptr) {
1722-
__parent = __hint.__ptr_;
1723-
return static_cast<__node_base_pointer>(__hint.__ptr_)->__right_;
1724-
} else {
1725-
__parent = __next.__ptr_;
1726-
return __parent->__left_;
1727-
}
1728-
}
1729-
// *next(__hint) <= __v
1730-
return __find_equal(__parent, __v);
1731-
}
1732-
// else __v == *__hint
1733-
__parent = __hint.__ptr_;
1734-
__dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
1735-
return __dummy;
1736-
}
1737-
17381724
template <class _Tp, class _Compare, class _Allocator>
17391725
void __tree<_Tp, _Compare, _Allocator>::__insert_node_at(
17401726
__end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT {
@@ -1753,10 +1739,9 @@ template <class _Tp, class _Compare, class _Allocator>
17531739
template <class _Key, class... _Args>
17541740
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
17551741
__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
1756-
__end_node_pointer __parent;
1757-
__node_base_pointer& __child = __find_equal(__parent, __k);
1758-
__node_pointer __r = static_cast<__node_pointer>(__child);
1759-
bool __inserted = false;
1742+
auto [__parent, __child] = __find_equal(__k);
1743+
__node_pointer __r = static_cast<__node_pointer>(__child);
1744+
bool __inserted = false;
17601745
if (__child == nullptr) {
17611746
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
17621747
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1771,11 +1756,10 @@ template <class _Key, class... _Args>
17711756
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
17721757
__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
17731758
const_iterator __p, _Key const& __k, _Args&&... __args) {
1774-
__end_node_pointer __parent;
17751759
__node_base_pointer __dummy;
1776-
__node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k);
1777-
__node_pointer __r = static_cast<__node_pointer>(__child);
1778-
bool __inserted = false;
1760+
auto [__parent, __child] = __find_equal(__p, __dummy, __k);
1761+
__node_pointer __r = static_cast<__node_pointer>(__child);
1762+
bool __inserted = false;
17791763
if (__child == nullptr) {
17801764
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
17811765
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1800,11 +1784,10 @@ template <class _Tp, class _Compare, class _Allocator>
18001784
template <class... _Args>
18011785
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
18021786
__tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) {
1803-
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1804-
__end_node_pointer __parent;
1805-
__node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1806-
__node_pointer __r = static_cast<__node_pointer>(__child);
1807-
bool __inserted = false;
1787+
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1788+
auto [__parent, __child] = __find_equal(__h->__value_);
1789+
__node_pointer __r = static_cast<__node_pointer>(__child);
1790+
bool __inserted = false;
18081791
if (__child == nullptr) {
18091792
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
18101793
__r = __h.release();
@@ -1818,10 +1801,9 @@ template <class... _Args>
18181801
typename __tree<_Tp, _Compare, _Allocator>::iterator
18191802
__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p, _Args&&... __args) {
18201803
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1821-
__end_node_pointer __parent;
18221804
__node_base_pointer __dummy;
1823-
__node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_);
1824-
__node_pointer __r = static_cast<__node_pointer>(__child);
1805+
auto [__parent, __child] = __find_equal(__p, __dummy, __h->__value_);
1806+
__node_pointer __r = static_cast<__node_pointer>(__child);
18251807
if (__child == nullptr) {
18261808
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
18271809
__r = __h.release();
@@ -1854,10 +1836,9 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Arg
18541836
template <class _Tp, class _Compare, class _Allocator>
18551837
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
18561838
__tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) {
1857-
__end_node_pointer __parent;
1858-
__node_base_pointer& __child = __find_equal(__parent, __v);
1859-
__node_pointer __r = static_cast<__node_pointer>(__child);
1860-
bool __inserted = false;
1839+
auto [__parent, __child] = __find_equal(__v);
1840+
__node_pointer __r = static_cast<__node_pointer>(__child);
1841+
bool __inserted = false;
18611842
if (__child == nullptr) {
18621843
__assign_value(__nd->__value_, __v);
18631844
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd));
@@ -1906,8 +1887,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n
19061887
return _InsertReturnType{end(), false, _NodeHandle()};
19071888

19081889
__node_pointer __ptr = __nh.__ptr_;
1909-
__end_node_pointer __parent;
1910-
__node_base_pointer& __child = __find_equal(__parent, __ptr->__value_);
1890+
auto [__parent, __child] = __find_equal(__ptr->__value_);
19111891
if (__child != nullptr)
19121892
return _InsertReturnType{iterator(static_cast<__node_pointer>(__child)), false, std::move(__nh)};
19131893

@@ -1924,10 +1904,9 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
19241904
return end();
19251905

19261906
__node_pointer __ptr = __nh.__ptr_;
1927-
__end_node_pointer __parent;
19281907
__node_base_pointer __dummy;
1929-
__node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, __ptr->__value_);
1930-
__node_pointer __r = static_cast<__node_pointer>(__child);
1908+
auto [__parent, __child] = __find_equal(__hint, __dummy, __ptr->__value_);
1909+
__node_pointer __r = static_cast<__node_pointer>(__child);
19311910
if (__child == nullptr) {
19321911
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
19331912
__r = __ptr;
@@ -1960,8 +1939,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg
19601939

19611940
for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) {
19621941
__node_pointer __src_ptr = __i.__get_np();
1963-
__end_node_pointer __parent;
1964-
__node_base_pointer& __child = __find_equal(__parent, __src_ptr->__value_);
1942+
auto [__parent, __child] = __find_equal(__src_ptr->__value_);
19651943
++__i;
19661944
if (__child != nullptr)
19671945
continue;

libcxx/include/map

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,9 +1428,8 @@ map<_Key, _Tp, _Compare, _Allocator>::__construct_node_with_key(const key_type&
14281428

14291429
template <class _Key, class _Tp, class _Compare, class _Allocator>
14301430
_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
1431-
__parent_pointer __parent;
1432-
__node_base_pointer& __child = __tree_.__find_equal(__parent, __k);
1433-
__node_pointer __r = static_cast<__node_pointer>(__child);
1431+
auto [__parent, __child] = __tree_.__find_equal(__k);
1432+
__node_pointer __r = static_cast<__node_pointer>(__child);
14341433
if (__child == nullptr) {
14351434
__node_holder __h = __construct_node_with_key(__k);
14361435
__tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1443,17 +1442,15 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
14431442

14441443
template <class _Key, class _Tp, class _Compare, class _Allocator>
14451444
_Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) {
1446-
__parent_pointer __parent;
1447-
__node_base_pointer& __child = __tree_.__find_equal(__parent, __k);
1445+
auto [_, __child] = __tree_.__find_equal(__k);
14481446
if (__child == nullptr)
14491447
std::__throw_out_of_range("map::at: key not found");
14501448
return static_cast<__node_pointer>(__child)->__value_.second;
14511449
}
14521450

14531451
template <class _Key, class _Tp, class _Compare, class _Allocator>
14541452
const _Tp& map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const {
1455-
__parent_pointer __parent;
1456-
__node_base_pointer __child = __tree_.__find_equal(__parent, __k);
1453+
auto [_, __child] = __tree_.__find_equal(__k);
14571454
if (__child == nullptr)
14581455
std::__throw_out_of_range("map::at: key not found");
14591456
return static_cast<__node_pointer>(__child)->__value_.second;

0 commit comments

Comments
 (0)