From d80ef87b9a0138759c18eb6422b4d85131df26d4 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:56:02 +0800 Subject: [PATCH 1/6] 1. the container is not necessarily reversible --- stl/inc/flat_set | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 18fb0f2553b..7748e05e732 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -172,29 +172,29 @@ public: } _NODISCARD reverse_iterator rbegin() noexcept { - return _Get_cont().rbegin(); + return reverse_iterator(end()); } _NODISCARD const_reverse_iterator rbegin() const noexcept { - return _Get_cont().rbegin(); + return const_reverse_iterator(end()); } _NODISCARD reverse_iterator rend() noexcept { - return _Get_cont().rend(); + return reverse_iterator(begin()); } _NODISCARD const_reverse_iterator rend() const noexcept { - return _Get_cont().rend(); + return const_reverse_iterator(begin()); } _NODISCARD const_iterator cbegin() const noexcept { - return _Get_cont().cbegin(); + return begin(); } _NODISCARD const_iterator cend() const noexcept { - return _Get_cont().cend(); + return end(); } _NODISCARD const_reverse_iterator crbegin() const noexcept { - return _Get_cont().crbegin(); + return rbegin(); } _NODISCARD const_reverse_iterator crend() const noexcept { - return _Get_cont().crend(); + return rend(); } // capacity From 8ae785dfdfeabf0ca0a1bc4253c55b76be03c482 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:21:06 +0800 Subject: [PATCH 2/6] 2. for private methods, use `static_assert` instead of constraints --- stl/inc/flat_set | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 7748e05e732..f8ef56e8ad6 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -556,8 +556,9 @@ private: } template - requires _Keylt_transparent || is_same_v<_Ty, _Kty> size_type _Erase(const _Ty& _Val) { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Ty, _Kty>); + const auto [_First, _Last] = equal_range(_Val); const auto _Removed = static_cast(_Last - _First); @@ -566,8 +567,9 @@ private: } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD iterator _Find(const _Other& _Val) { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Other, _Kty>); + const iterator _End = end(); const iterator _Where = lower_bound(_Val); if (_Where != _End && _Keys_equal(*_Where, _Val)) { @@ -578,8 +580,9 @@ private: } template - requires _Keylt_transparent || is_same_v<_Other, _Kty> _NODISCARD const_iterator _Find(const _Other& _Val) const { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Other, _Kty>); + const const_iterator _End = cend(); const const_iterator _Where = lower_bound(_Val); if (_Where != _End && _Keys_equal(*_Where, _Val)) { @@ -590,8 +593,9 @@ private: } template - requires _Keylt_transparent || (is_same_v<_Kty, _Lhty> && is_same_v<_Lhty, _Rhty>) _NODISCARD bool _Keys_equal(const _Lhty& _Lhs, const _Rhty& _Rhs) const { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || (is_same_v<_Kty, _Lhty> && is_same_v<_Lhty, _Rhty>) ); + const key_compare& _Compare = _Get_comp(); return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); } From b8944b6ba695780446cbdfc8dfcf5ad6d29b8d34 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:23:05 +0800 Subject: [PATCH 3/6] 3. nitpicks --- stl/inc/flat_set | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index f8ef56e8ad6..5b4a798cf09 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -566,9 +566,9 @@ private: return _Removed; } - template - _NODISCARD iterator _Find(const _Other& _Val) { - _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Other, _Kty>); + template + _NODISCARD iterator _Find(const _Ty& _Val) { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Ty, _Kty>); const iterator _End = end(); const iterator _Where = lower_bound(_Val); @@ -579,9 +579,9 @@ private: } } - template - _NODISCARD const_iterator _Find(const _Other& _Val) const { - _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Other, _Kty>); + template + _NODISCARD const_iterator _Find(const _Ty& _Val) const { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Ty, _Kty>); const const_iterator _End = cend(); const const_iterator _Where = lower_bound(_Val); @@ -614,7 +614,8 @@ private: template void _Restore_invariants_after_insert(const size_type _Old_size) { const key_compare& _Compare = _Get_comp(); - const iterator _Old_end = begin() + static_cast(_Old_size); + const iterator _Begin = begin(); + const iterator _Old_end = _Begin + static_cast(_Old_size); const iterator _New_end = end(); if constexpr (!_Presorted) { @@ -623,9 +624,9 @@ private: _STL_ASSERT(_STD is_sorted(_Old_end, _New_end, _Compare), "Input was not sorted!"); } - _STD inplace_merge(begin(), _Old_end, _New_end, _Compare); + _STD inplace_merge(_Begin, _Old_end, _New_end, _Compare); - _STL_INTERNAL_CHECK(_STD is_sorted(begin(), end(), _Compare)); + _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _New_end, _Compare)); _Erase_dupes_if_needed(); } From 53591cd2ecbc0d339cb60ebed23ee906cb475c97 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 17:49:05 +0800 Subject: [PATCH 4/6] 4. apply `_Pass_fn` when passing to algorithm; apply `_DEBUG_LT_PRED` when doing single comparision --- stl/inc/flat_set | 95 +++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 5b4a798cf09..51dee45987b 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -350,66 +350,66 @@ public: } _NODISCARD bool contains(const _Kty& _Val) const { - return _STD binary_search(cbegin(), cend(), _Val, _Get_comp()); + return _STD binary_search(cbegin(), cend(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD bool contains(const _Other& _Val) const { - return _STD binary_search(cbegin(), cend(), _Val, _Get_comp()); + return _STD binary_search(cbegin(), cend(), _Val, _Get_comp_v()); } _NODISCARD iterator lower_bound(const _Kty& _Val) { - return _STD lower_bound(begin(), end(), _Val, _Get_comp()); + return _STD lower_bound(begin(), end(), _Val, _Get_comp_v()); } _NODISCARD const_iterator lower_bound(const _Kty& _Val) const { - return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); + return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD iterator lower_bound(const _Other& _Val) { - return _STD lower_bound(begin(), end(), _Val, _Get_comp()); + return _STD lower_bound(begin(), end(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD const_iterator lower_bound(const _Other& _Val) const { - return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp()); + return _STD lower_bound(cbegin(), cend(), _Val, _Get_comp_v()); } _NODISCARD iterator upper_bound(const _Kty& _Val) { - return _STD upper_bound(begin(), end(), _Val, _Get_comp()); + return _STD upper_bound(begin(), end(), _Val, _Get_comp_v()); } _NODISCARD const_iterator upper_bound(const _Kty& _Val) const { - return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); + return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD iterator upper_bound(const _Other& _Val) { - return _STD upper_bound(begin(), end(), _Val, _Get_comp()); + return _STD upper_bound(begin(), end(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD const_iterator upper_bound(const _Other& _Val) const { - return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp()); + return _STD upper_bound(cbegin(), cend(), _Val, _Get_comp_v()); } _NODISCARD pair equal_range(const _Kty& _Val) { - return _STD equal_range(begin(), end(), _Val, _Get_comp()); + return _STD equal_range(begin(), end(), _Val, _Get_comp_v()); } _NODISCARD pair equal_range(const _Kty& _Val) const { - return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); + return _STD equal_range(cbegin(), cend(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) { - return _STD equal_range(begin(), end(), _Val, _Get_comp()); + return _STD equal_range(begin(), end(), _Val, _Get_comp_v()); } template requires _Keylt_transparent _NODISCARD pair equal_range(const _Other& _Val) const { - return _STD equal_range(cbegin(), cend(), _Val, _Get_comp()); + return _STD equal_range(cbegin(), cend(), _Val, _Get_comp_v()); } _NODISCARD friend bool operator==(const _Deriv& _Lhs, const _Deriv& _Rhs) { @@ -427,7 +427,7 @@ public: private: void _Assert_after_sorted_input() const { - _STL_ASSERT(_STD is_sorted(cbegin(), cend(), _Get_comp()), "Input was not sorted!"); + _STL_ASSERT(_STD is_sorted(cbegin(), cend(), _Get_comp_v()), "Input was not sorted!"); if constexpr (!_Multi) { _STL_ASSERT(_Is_unique(), "Input was sorted but not unique!"); } @@ -449,7 +449,6 @@ private: bool _Check_where(const const_iterator _Where, const _Kty& _Val) const { // check that _Val can be inserted before _Where - const key_compare& _Compare = _Get_comp(); if constexpr (_Multi) { // check that _Where is the upper_bound for _Val // equivalent to checking *(_Where-1) <= _Val < *_Where @@ -491,7 +490,7 @@ private: template iterator _Emplace_hint(const_iterator _Where, _Ty&& _Val) { _Container& _Cont = _Get_cont(); - const key_compare& _Compare = _Get_comp(); + auto _Comp = _Get_comp_v(); const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); @@ -503,11 +502,11 @@ private: // _Val >= *(_Where-1) ~ upper_bound is _Where } else { // _Val < *(_Where-1) ~ upper_bound is in [_Begin,_Where-1] - _Where = _STD upper_bound(_Begin, _Where - 1, _Val, _Compare); + _Where = _STD upper_bound(_Begin, _Where - 1, _Val, _Comp); } } else { // _Val >= *_Where ~ upper_bound is in [_Where+1,_End] - _Where = _STD upper_bound(_Where + 1, _End, _Val, _Compare); + _Where = _STD upper_bound(_Where + 1, _End, _Val, _Comp); } } else { // look for the lower_bound for flat_set @@ -517,11 +516,11 @@ private: // _Val > *(_Where-1) ~ lower_bound is _Where } else { // _Val <= *(_Where-1) ~ lower_bound is in [_Begin,_Where-1] - _Where = _STD lower_bound(_Begin, _Where - 1, _Val, _Compare); + _Where = _STD lower_bound(_Begin, _Where - 1, _Val, _Comp); } } else { // _Val > *_Where ~ lower_bound is in [_Where+1,_End] - _Where = _STD lower_bound(_Where + 1, _End, _Val, _Compare); + _Where = _STD lower_bound(_Where + 1, _End, _Val, _Comp); } } @@ -592,14 +591,6 @@ private: } } - template - _NODISCARD bool _Keys_equal(const _Lhty& _Lhs, const _Rhty& _Rhs) const { - _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || (is_same_v<_Kty, _Lhty> && is_same_v<_Lhty, _Rhty>) ); - - const key_compare& _Compare = _Get_comp(); - return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); - } - void _Erase_dupes_if_needed() { if constexpr (!_Multi) { const iterator _End = end(); @@ -613,20 +604,20 @@ private: template void _Restore_invariants_after_insert(const size_type _Old_size) { - const key_compare& _Compare = _Get_comp(); - const iterator _Begin = begin(); - const iterator _Old_end = _Begin + static_cast(_Old_size); - const iterator _New_end = end(); + auto _Comp = _Get_comp_v(); + const iterator _Begin = begin(); + const iterator _Old_end = _Begin + static_cast(_Old_size); + const iterator _New_end = end(); if constexpr (!_Presorted) { - _STD sort(_Old_end, _New_end, _Compare); + _STD sort(_Old_end, _New_end, _Comp); } else { - _STL_ASSERT(_STD is_sorted(_Old_end, _New_end, _Compare), "Input was not sorted!"); + _STL_ASSERT(_STD is_sorted(_Old_end, _New_end, _Comp), "Input was not sorted!"); } - _STD inplace_merge(_Begin, _Old_end, _New_end, _Compare); + _STD inplace_merge(_Begin, _Old_end, _New_end, _Comp); - _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _New_end, _Compare)); + _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _New_end, _Comp)); _Erase_dupes_if_needed(); } @@ -640,17 +631,33 @@ private: } // O(N) if already sorted. - const key_compare& _Compare = _Get_comp(); - const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Compare); + auto _Comp = _Get_comp_v(); + const iterator _Begin_unsorted = _STD is_sorted_until(_Begin, _End, _Comp); - _STD sort(_Begin_unsorted, _End, _Compare); - _STD inplace_merge(_Begin, _Begin_unsorted, _End, _Compare); + _STD sort(_Begin_unsorted, _End, _Comp); + _STD inplace_merge(_Begin, _Begin_unsorted, _End, _Comp); - _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _End, _Compare)); + _STL_INTERNAL_CHECK(_STD is_sorted(_Begin, _End, _Comp)); _Erase_dupes_if_needed(); } + template + _NODISCARD bool _Compare(const _Lty& _Lhs, const _Rty& _Rhs) const + noexcept(noexcept(_DEBUG_LT_PRED(_My_pair._Get_first(), _Lhs, _Rhs))) { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || (is_same_v<_Kty, _Lty> && is_same_v<_Kty, _Rty>) ); + + return _DEBUG_LT_PRED(_My_pair._Get_first(), _Lhs, _Rhs); + } + + template + _NODISCARD bool _Keys_equal(const _Lty& _Lhs, const _Rty& _Rhs) const + noexcept(noexcept(!_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs))) { + _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || (is_same_v<_Kty, _Lty> && is_same_v<_Kty, _Rty>) ); + + return !_Compare(_Lhs, _Rhs) && !_Compare(_Rhs, _Lhs); + } + _NODISCARD const _Container& _Get_cont() const noexcept { return _My_pair._Myval2; } @@ -667,6 +674,10 @@ private: return _My_pair._Get_first(); } + _NODISCARD auto _Get_comp_v() const noexcept { + return _STD _Pass_fn(_My_pair._Get_first()); + } + _Compressed_pair _My_pair; }; From 50000dcbd3b0a1b0bac8379b27806c2a59411996 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:10:07 +0800 Subject: [PATCH 5/6] 5. replace some `_Keys_equal` with single comparision --- stl/inc/flat_set | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 51dee45987b..9ec6d706885 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -471,7 +471,7 @@ private: } else { const iterator _End = end(); const iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { + if (_Where != _End && !_Compare(_Val, *_Where)) { return pair{_Where, false}; } @@ -529,7 +529,7 @@ private: _STL_INTERNAL_CHECK(_Check_where(_Where, _Val)); return _Cont.emplace(_Where, _STD forward<_Ty>(_Val)); } else { - if (_Where != _End && _Keys_equal(_Val, *_Where)) { + if (_Where != _End && !_Compare(_Val, *_Where)) { return _Cont.begin() + (_Where - _Begin); } @@ -571,7 +571,7 @@ private: const iterator _End = end(); const iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { + if (_Where != _End && !_Compare(_Val, *_Where)) { return _Where; } else { return _End; @@ -584,7 +584,7 @@ private: const const_iterator _End = cend(); const const_iterator _Where = lower_bound(_Val); - if (_Where != _End && _Keys_equal(*_Where, _Val)) { + if (_Where != _End && !_Compare(_Val, *_Where)) { return _Where; } else { return _End; From 40ea0386a72b32d3fcace5a558220e9f1f382bc7 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:38:33 +0800 Subject: [PATCH 6/6] 6. optimize `flat_set.count(const key&)` and `flat_set.erase(const key&)` --- stl/inc/flat_set | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/stl/inc/flat_set b/stl/inc/flat_set index 9ec6d706885..d39368763f7 100644 --- a/stl/inc/flat_set +++ b/stl/inc/flat_set @@ -339,8 +339,12 @@ public: } _NODISCARD size_type count(const _Kty& _Val) const { - const auto [_First, _Last] = equal_range(_Val); - return static_cast(_Last - _First); + if constexpr (!_Multi) { + return contains(_Val); + } else { + const auto [_First, _Last] = equal_range(_Val); + return static_cast(_Last - _First); + } } template requires _Keylt_transparent @@ -558,11 +562,20 @@ private: size_type _Erase(const _Ty& _Val) { _STL_INTERNAL_STATIC_ASSERT(_Keylt_transparent || is_same_v<_Ty, _Kty>); - const auto [_First, _Last] = equal_range(_Val); + if constexpr (!_Multi && is_same_v<_Ty, _Kty>) { + const iterator _Where = lower_bound(_Val); + if (_Where != end() && !_Compare(_Val, *_Where)) { + _Get_cont().erase(_Where); + return 1; + } + return 0; + } else { + const auto [_First, _Last] = equal_range(_Val); - const auto _Removed = static_cast(_Last - _First); - _Get_cont().erase(_First, _Last); - return _Removed; + const auto _Removed = static_cast(_Last - _First); + _Get_cont().erase(_First, _Last); + return _Removed; + } } template