diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 1e6eac4961b..d50232d3b1e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1099,25 +1099,14 @@ private: return _Count; } - template - _NODISCARD iterator _Find(const _KeyTy& _Key_val) { + template + _NODISCARD auto _Find(this _SelfTy& _Self, const _KeyTy& _Key_val) { _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - iterator _Position = lower_bound(_Key_val); - if (_Position != end() && !_Key_compare(_Key_val, _Position->first)) { + const auto _Position = _Self.lower_bound(_Key_val); + if (_Position != _Self.end() && !_Self._Key_compare(_Key_val, _Position->first)) { return _Position; } else { - return end(); - } - } - - template - _NODISCARD const_iterator _Find(const _KeyTy& _Key_val) const { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const_iterator _Position = lower_bound(_Key_val); - if (_Position != cend() && !_Key_compare(_Key_val, _Position->first)) { - return _Position; - } else { - return cend(); + return _Self.end(); } } @@ -1133,74 +1122,37 @@ private: return find(_Key_val) != cend(); } - template - _NODISCARD iterator _Lower_bound(const _KeyTy& _Key_val) { + template + _NODISCARD auto _Find_bound(this _SelfTy& _Self, const _KeyTy& _Key_val, _BoundFn _Bound_fun) { _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Key_unchecked_begin = _STD _Get_unwrapped(_STD cbegin(_Data.keys)); - const auto _Key_unchecked_it = _STD lower_bound( - _Key_unchecked_begin, _STD _Get_unwrapped(_STD cend(_Data.keys)), _Key_val, _Pass_key_comp()); + const auto _Key_unchecked_begin = _STD _Get_unwrapped(_STD cbegin(_Self._Data.keys)); + const auto _Key_unchecked_it = _Bound_fun( + _Key_unchecked_begin, _STD _Get_unwrapped(_STD cend(_Self._Data.keys)), _Key_val, _Self._Pass_key_comp()); const auto _Dist = _Key_unchecked_it - _Key_unchecked_begin; - auto _Key_it = _STD cbegin(_Data.keys); - _STD _Seek_wrapped(_Key_it, _Key_unchecked_it); - auto _Val_it = _Data.values.begin() + static_cast<_RANGES range_difference_t<_MappedContainer>>(_Dist); - return iterator{_STD move(_Key_it), _STD move(_Val_it)}; - } - - template - _NODISCARD const_iterator _Lower_bound(const _KeyTy& _Key_val) const { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Key_unchecked_begin = _STD _Get_unwrapped(_STD cbegin(_Data.keys)); - const auto _Key_unchecked_it = _STD lower_bound( - _Key_unchecked_begin, _STD _Get_unwrapped(_STD cend(_Data.keys)), _Key_val, _Pass_key_comp()); - const auto _Dist = _Key_unchecked_it - _Key_unchecked_begin; - - auto _Key_it = _STD cbegin(_Data.keys); + auto _Key_it = _STD cbegin(_Self._Data.keys); _STD _Seek_wrapped(_Key_it, _Key_unchecked_it); auto _Val_it = - _STD cbegin(_Data.values) + static_cast<_RANGES range_difference_t>(_Dist); - return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; - } - - template - _NODISCARD iterator _Upper_bound(const _KeyTy& _Key_val) { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Key_unchecked_begin = _STD _Get_unwrapped(_STD cbegin(_Data.keys)); - const auto _Key_unchecked_it = _STD upper_bound( - _Key_unchecked_begin, _STD _Get_unwrapped(_STD cend(_Data.keys)), _Key_val, _Pass_key_comp()); - const auto _Dist = _Key_unchecked_it - _Key_unchecked_begin; + _STD begin(_Self._Data.values) + static_cast<_RANGES range_difference_t>(_Dist); - auto _Key_it = _STD cbegin(_Data.keys); - _STD _Seek_wrapped(_Key_it, _Key_unchecked_it); - auto _Val_it = _Data.values.begin() + static_cast<_RANGES range_difference_t<_MappedContainer>>(_Dist); - return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + using _Maybe_const_iter = conditional_t, const_iterator, iterator>; + return _Maybe_const_iter{_STD move(_Key_it), _STD move(_Val_it)}; } - template - _NODISCARD const_iterator _Upper_bound(const _KeyTy& _Key_val) const { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Key_unchecked_begin = _STD _Get_unwrapped(_STD cbegin(_Data.keys)); - const auto _Key_unchecked_it = _STD upper_bound( - _Key_unchecked_begin, _STD _Get_unwrapped(_STD cend(_Data.keys)), _Key_val, _Pass_key_comp()); - const auto _Dist = _Key_unchecked_it - _Key_unchecked_begin; - - auto _Key_it = _STD cbegin(_Data.keys); - _STD _Seek_wrapped(_Key_it, _Key_unchecked_it); - auto _Val_it = - _STD cbegin(_Data.values) + static_cast<_RANGES range_difference_t>(_Dist); - return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + template + _NODISCARD auto _Lower_bound(this _SelfTy& _Self, const _KeyTy& _Key_val) { + return _Self._Find_bound(_Key_val, _RANGES lower_bound); } - template - _NODISCARD pair _Equal_range(const _KeyTy& _Key_val) { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - return {lower_bound(_Key_val), upper_bound(_Key_val)}; + template + _NODISCARD auto _Upper_bound(this _SelfTy& _Self, const _KeyTy& _Key_val) { + return _Self._Find_bound(_Key_val, _RANGES upper_bound); } - template - _NODISCARD pair _Equal_range(const _KeyTy& _Key_val) const { + template + _NODISCARD auto _Equal_range(this _SelfTy& _Self, const _KeyTy& _Key_val) { _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - return {lower_bound(_Key_val), upper_bound(_Key_val)}; + return pair{_Self.lower_bound(_Key_val), _Self.upper_bound(_Key_val)}; } }; @@ -1399,22 +1351,11 @@ private: using _Mybase::_Key_equal; using _Mybase::_Pass_key_comp; - template - _NODISCARD mapped_type& _At(const _KeyTy& _Key_val) { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Position = this->find(_Key_val); - if (_Position == this->end()) { - _Xout_of_range("invalid flat_map key"); - } - - return _Position->second; - } - - template - _NODISCARD const mapped_type& _At(const _KeyTy& _Key_val) const { + template + _NODISCARD auto& _At(this _SelfTy& _Self, const _KeyTy& _Key_val) { _STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent); - const auto _Position = this->find(_Key_val); - if (_Position == this->end()) { + const auto _Position = _Self.find(_Key_val); + if (_Position == _Self.end()) { _Xout_of_range("invalid flat_map key"); } diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 74e88ddc81d..fac98c6ff64 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -766,6 +766,29 @@ void test_throwing_compare_swap() { test_throwing_compare_swap_single(); } +// Test that changes in GH-5987 did not break calls of lookup member functions by using deducing this. +template +void test_lookup_call_on_temporaries_single() { + (void) T{}.lower_bound(42); + (void) T{}.lower_bound('a'); + (void) T{}.upper_bound(42); + (void) T{}.upper_bound('a'); + (void) T{}.equal_range(42); + (void) T{}.equal_range('a'); + (void) T{}.find(42); + (void) T{}.find('a'); +} + +void test_lookup_call_on_temporaries() { + test_lookup_call_on_temporaries_single>(); + test_lookup_call_on_temporaries_single>(); + try { + (void) flat_map{}.at(42); + (void) flat_map{}.at('a'); + } catch (...) { + } +} + int main() { test_construction(); test_pointer_to_incomplete_type(); @@ -776,4 +799,5 @@ int main() { test_insert_or_assign(); test_comparison(); test_throwing_compare_swap(); + test_lookup_call_on_temporaries(); }