Skip to content

Commit cda1e94

Browse files
committed
[libc++] Refactor __tree::__find_equal to not have an out parameter
1 parent 7cd1796 commit cda1e94

File tree

2 files changed

+98
-123
lines changed

2 files changed

+98
-123
lines changed

libcxx/include/__tree

Lines changed: 94 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,15 +1169,89 @@ public:
11691169

11701170
// FIXME: Make this function const qualified. Unfortunately doing so
11711171
// breaks existing code which uses non-const callable comparators.
1172+
1173+
// Find place to insert if __v doesn't exist
1174+
// Set __parent to parent of null leaf
1175+
// Return reference to null leaf
1176+
// If __v exists, set parent to node of __v and return reference to node of __v
11721177
template <class _Key>
1173-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v);
1178+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) {
1179+
using _PairT = pair<__end_node_pointer, __node_base_pointer&>;
1180+
1181+
__node_pointer __node = __root();
1182+
1183+
if (__node == nullptr) {
1184+
auto __end = __end_node();
1185+
return _PairT(__end, __end->__left_);
1186+
}
1187+
1188+
__node_base_pointer* __node_ptr = __root_ptr();
1189+
while (true) {
1190+
if (value_comp()(__v, __node->__value_)) {
1191+
if (__node->__left_ == nullptr)
1192+
return _PairT(static_cast<__end_node_pointer>(__node), __node->__left_);
1193+
1194+
__node_ptr = std::addressof(__node->__left_);
1195+
__node = static_cast<__node_pointer>(__node->__left_);
1196+
} else if (value_comp()(__node->__value_, __v)) {
1197+
if (__node->__right_ == nullptr)
1198+
return _PairT(__node, __node->__right_);
1199+
1200+
__node_ptr = std::addressof(__node->__right_);
1201+
__node = static_cast<__node_pointer>(__node->__right_);
1202+
} else {
1203+
return _PairT(static_cast<__end_node_pointer>(__node), *__node_ptr);
1204+
}
1205+
}
1206+
}
1207+
11741208
template <class _Key>
1175-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__end_node_pointer& __parent, const _Key& __v) const {
1176-
return const_cast<__tree*>(this)->__find_equal(__parent, __v);
1209+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&> __find_equal(const _Key& __v) const {
1210+
return const_cast<__tree*>(this)->__find_equal(__v);
11771211
}
1212+
1213+
// Find place to insert if __v doesn't exist
1214+
// First check prior to __hint.
1215+
// Next check after __hint.
1216+
// Next do O(log N) search.
1217+
// Set __parent to parent of null leaf
1218+
// Return reference to null leaf
1219+
// If __v exists, set parent to node of __v and return reference to node of __v
11781220
template <class _Key>
1179-
_LIBCPP_HIDE_FROM_ABI __node_base_pointer&
1180-
__find_equal(const_iterator __hint, __end_node_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v);
1221+
_LIBCPP_HIDE_FROM_ABI pair<__end_node_pointer, __node_base_pointer&>
1222+
__find_equal(const_iterator __hint, __node_base_pointer& __dummy, const _Key& __v) {
1223+
using _PairT = pair<__end_node_pointer, __node_base_pointer&>;
1224+
1225+
if (__hint == end() || value_comp()(__v, *__hint)) { // check before
1226+
// __v < *__hint
1227+
const_iterator __prior = __hint;
1228+
if (__prior == begin() || value_comp()(*--__prior, __v)) {
1229+
// *prev(__hint) < __v < *__hint
1230+
if (__hint.__ptr_->__left_ == nullptr)
1231+
return _PairT(__hint.__ptr_, __hint.__ptr_->__left_);
1232+
return _PairT(__prior.__ptr_, static_cast<__node_pointer>(__prior.__ptr_)->__right_);
1233+
}
1234+
// __v <= *prev(__hint)
1235+
return __find_equal(__v);
1236+
}
1237+
1238+
if (value_comp()(*__hint, __v)) { // check after
1239+
// *__hint < __v
1240+
const_iterator __next = std::next(__hint);
1241+
if (__next == end() || value_comp()(__v, *__next)) {
1242+
// *__hint < __v < *std::next(__hint)
1243+
if (__hint.__get_np()->__right_ == nullptr)
1244+
return _PairT(__hint.__ptr_, static_cast<__node_pointer>(__hint.__ptr_)->__right_);
1245+
return _PairT(__next.__ptr_, __next.__ptr_->__left_);
1246+
}
1247+
// *next(__hint) <= __v
1248+
return __find_equal(__v);
1249+
}
1250+
1251+
// else __v == *__hint
1252+
__dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
1253+
return _PairT(__hint.__ptr_, __dummy);
1254+
}
11811255

11821256
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __tree& __t) {
11831257
__copy_assign_alloc(__t, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
@@ -1620,94 +1694,6 @@ typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Co
16201694
return __find_leaf_low(__parent, __v);
16211695
}
16221696

1623-
// Find place to insert if __v doesn't exist
1624-
// Set __parent to parent of null leaf
1625-
// Return reference to null leaf
1626-
// If __v exists, set parent to node of __v and return reference to node of __v
1627-
template <class _Tp, class _Compare, class _Allocator>
1628-
template <class _Key>
1629-
typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer&
1630-
__tree<_Tp, _Compare, _Allocator>::__find_equal(__end_node_pointer& __parent, const _Key& __v) {
1631-
__node_pointer __nd = __root();
1632-
__node_base_pointer* __nd_ptr = __root_ptr();
1633-
if (__nd != nullptr) {
1634-
while (true) {
1635-
if (value_comp()(__v, __nd->__value_)) {
1636-
if (__nd->__left_ != nullptr) {
1637-
__nd_ptr = std::addressof(__nd->__left_);
1638-
__nd = static_cast<__node_pointer>(__nd->__left_);
1639-
} else {
1640-
__parent = static_cast<__end_node_pointer>(__nd);
1641-
return __parent->__left_;
1642-
}
1643-
} else if (value_comp()(__nd->__value_, __v)) {
1644-
if (__nd->__right_ != nullptr) {
1645-
__nd_ptr = std::addressof(__nd->__right_);
1646-
__nd = static_cast<__node_pointer>(__nd->__right_);
1647-
} else {
1648-
__parent = static_cast<__end_node_pointer>(__nd);
1649-
return __nd->__right_;
1650-
}
1651-
} else {
1652-
__parent = static_cast<__end_node_pointer>(__nd);
1653-
return *__nd_ptr;
1654-
}
1655-
}
1656-
}
1657-
__parent = __end_node();
1658-
return __parent->__left_;
1659-
}
1660-
1661-
// Find place to insert if __v doesn't exist
1662-
// First check prior to __hint.
1663-
// Next check after __hint.
1664-
// Next do O(log N) search.
1665-
// Set __parent to parent of null leaf
1666-
// Return reference to null leaf
1667-
// If __v exists, set parent to node of __v and return reference to node of __v
1668-
template <class _Tp, class _Compare, class _Allocator>
1669-
template <class _Key>
1670-
typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& __tree<_Tp, _Compare, _Allocator>::__find_equal(
1671-
const_iterator __hint, __end_node_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v) {
1672-
if (__hint == end() || value_comp()(__v, *__hint)) // check before
1673-
{
1674-
// __v < *__hint
1675-
const_iterator __prior = __hint;
1676-
if (__prior == begin() || value_comp()(*--__prior, __v)) {
1677-
// *prev(__hint) < __v < *__hint
1678-
if (__hint.__ptr_->__left_ == nullptr) {
1679-
__parent = __hint.__ptr_;
1680-
return __parent->__left_;
1681-
} else {
1682-
__parent = __prior.__ptr_;
1683-
return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_;
1684-
}
1685-
}
1686-
// __v <= *prev(__hint)
1687-
return __find_equal(__parent, __v);
1688-
} else if (value_comp()(*__hint, __v)) // check after
1689-
{
1690-
// *__hint < __v
1691-
const_iterator __next = std::next(__hint);
1692-
if (__next == end() || value_comp()(__v, *__next)) {
1693-
// *__hint < __v < *std::next(__hint)
1694-
if (__hint.__get_np()->__right_ == nullptr) {
1695-
__parent = __hint.__ptr_;
1696-
return static_cast<__node_base_pointer>(__hint.__ptr_)->__right_;
1697-
} else {
1698-
__parent = __next.__ptr_;
1699-
return __parent->__left_;
1700-
}
1701-
}
1702-
// *next(__hint) <= __v
1703-
return __find_equal(__parent, __v);
1704-
}
1705-
// else __v == *__hint
1706-
__parent = __hint.__ptr_;
1707-
__dummy = static_cast<__node_base_pointer>(__hint.__ptr_);
1708-
return __dummy;
1709-
}
1710-
17111697
template <class _Tp, class _Compare, class _Allocator>
17121698
void __tree<_Tp, _Compare, _Allocator>::__insert_node_at(
17131699
__end_node_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT {
@@ -1726,10 +1712,9 @@ template <class _Tp, class _Compare, class _Allocator>
17261712
template <class _Key, class... _Args>
17271713
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
17281714
__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
1729-
__end_node_pointer __parent;
1730-
__node_base_pointer& __child = __find_equal(__parent, __k);
1731-
__node_pointer __r = static_cast<__node_pointer>(__child);
1732-
bool __inserted = false;
1715+
auto [__parent, __child] = __find_equal(__k);
1716+
__node_pointer __r = static_cast<__node_pointer>(__child);
1717+
bool __inserted = false;
17331718
if (__child == nullptr) {
17341719
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
17351720
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1744,11 +1729,10 @@ template <class _Key, class... _Args>
17441729
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
17451730
__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args(
17461731
const_iterator __p, _Key const& __k, _Args&&... __args) {
1747-
__end_node_pointer __parent;
17481732
__node_base_pointer __dummy;
1749-
__node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k);
1750-
__node_pointer __r = static_cast<__node_pointer>(__child);
1751-
bool __inserted = false;
1733+
auto [__parent, __child] = __find_equal(__p, __dummy, __k);
1734+
__node_pointer __r = static_cast<__node_pointer>(__child);
1735+
bool __inserted = false;
17521736
if (__child == nullptr) {
17531737
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
17541738
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1774,8 +1758,7 @@ template <class... _Args>
17741758
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
17751759
__tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) {
17761760
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1777-
__end_node_pointer __parent;
1778-
__node_base_pointer& __child = __find_equal(__parent, __h->__value_);
1761+
auto [__parent, __child] = __find_equal(__h->__value_);
17791762
__node_pointer __r = static_cast<__node_pointer>(__child);
17801763
bool __inserted = false;
17811764
if (__child == nullptr) {
@@ -1791,10 +1774,9 @@ template <class... _Args>
17911774
typename __tree<_Tp, _Compare, _Allocator>::iterator
17921775
__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p, _Args&&... __args) {
17931776
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1794-
__end_node_pointer __parent;
17951777
__node_base_pointer __dummy;
1796-
__node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_);
1797-
__node_pointer __r = static_cast<__node_pointer>(__child);
1778+
auto [__parent, __child] = __find_equal(__p, __dummy, __h->__value_);
1779+
__node_pointer __r = static_cast<__node_pointer>(__child);
17981780
if (__child == nullptr) {
17991781
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
18001782
__r = __h.release();
@@ -1827,8 +1809,7 @@ __tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, _Arg
18271809
template <class _Tp, class _Compare, class _Allocator>
18281810
pair<typename __tree<_Tp, _Compare, _Allocator>::iterator, bool>
18291811
__tree<_Tp, _Compare, _Allocator>::__node_assign_unique(const value_type& __v, __node_pointer __nd) {
1830-
__end_node_pointer __parent;
1831-
__node_base_pointer& __child = __find_equal(__parent, __v);
1812+
auto [__parent, __child] = __find_equal(__v);
18321813
__node_pointer __r = static_cast<__node_pointer>(__child);
18331814
bool __inserted = false;
18341815
if (__child == nullptr) {
@@ -1879,8 +1860,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(_NodeHandle&& __n
18791860
return _InsertReturnType{end(), false, _NodeHandle()};
18801861

18811862
__node_pointer __ptr = __nh.__ptr_;
1882-
__end_node_pointer __parent;
1883-
__node_base_pointer& __child = __find_equal(__parent, __ptr->__value_);
1863+
auto [__parent, __child] = __find_equal(__ptr->__value_);
18841864
if (__child != nullptr)
18851865
return _InsertReturnType{iterator(static_cast<__node_pointer>(__child)), false, std::move(__nh)};
18861866

@@ -1897,10 +1877,9 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique(const_iterator __
18971877
return end();
18981878

18991879
__node_pointer __ptr = __nh.__ptr_;
1900-
__end_node_pointer __parent;
19011880
__node_base_pointer __dummy;
1902-
__node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, __ptr->__value_);
1903-
__node_pointer __r = static_cast<__node_pointer>(__child);
1881+
auto [__parent, __child] = __find_equal(__hint, __dummy, __ptr->__value_);
1882+
__node_pointer __r = static_cast<__node_pointer>(__child);
19041883
if (__child == nullptr) {
19051884
__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr));
19061885
__r = __ptr;
@@ -1932,9 +1911,8 @@ _LIBCPP_HIDE_FROM_ABI void __tree<_Tp, _Compare, _Allocator>::__node_handle_merg
19321911
static_assert(is_same<typename _Tree::__node_pointer, __node_pointer>::value, "");
19331912

19341913
for (typename _Tree::iterator __i = __source.begin(); __i != __source.end();) {
1935-
__node_pointer __src_ptr = __i.__get_np();
1936-
__end_node_pointer __parent;
1937-
__node_base_pointer& __child = __find_equal(__parent, __src_ptr->__value_);
1914+
__node_pointer __src_ptr = __i.__get_np();
1915+
auto [__parent, __child] = __find_equal(__src_ptr->__value_);
19381916
++__i;
19391917
if (__child != nullptr)
19401918
continue;

libcxx/include/map

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

14271427
template <class _Key, class _Tp, class _Compare, class _Allocator>
14281428
_Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
1429-
__parent_pointer __parent;
1430-
__node_base_pointer& __child = __tree_.__find_equal(__parent, __k);
1431-
__node_pointer __r = static_cast<__node_pointer>(__child);
1429+
auto [__parent, __child] = __tree_.__find_equal(__k);
1430+
__node_pointer __r = static_cast<__node_pointer>(__child);
14321431
if (__child == nullptr) {
14331432
__node_holder __h = __construct_node_with_key(__k);
14341433
__tree_.__insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get()));
@@ -1441,17 +1440,15 @@ _Tp& map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k) {
14411440

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

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

0 commit comments

Comments
 (0)