Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 27 additions & 86 deletions stl/inc/flat_map
Original file line number Diff line number Diff line change
Expand Up @@ -1099,25 +1099,14 @@ private:
return _Count;
}

template <class _KeyTy>
_NODISCARD iterator _Find(const _KeyTy& _Key_val) {
template <class _SelfTy, class _KeyTy>
_NODISCARD auto _Find(this _SelfTy& _Self, const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
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 <class _KeyTy>
_NODISCARD const_iterator _Find(const _KeyTy& _Key_val) const {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
const_iterator _Position = lower_bound(_Key_val);
if (_Position != cend() && !_Key_compare(_Key_val, _Position->first)) {
return _Position;
} else {
return cend();
return _Self.end();
}
}

Expand All @@ -1133,74 +1122,37 @@ private:
return find(_Key_val) != cend();
}

template <class _KeyTy>
_NODISCARD iterator _Lower_bound(const _KeyTy& _Key_val) {
template <class _SelfTy, class _KeyTy, class _BoundFn>
_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<key_compare>);
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 <class _KeyTy>
_NODISCARD const_iterator _Lower_bound(const _KeyTy& _Key_val) const {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
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<const _MappedContainer>>(_Dist);
return const_iterator{_STD move(_Key_it), _STD move(_Val_it)};
}

template <class _KeyTy>
_NODISCARD iterator _Upper_bound(const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
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<mapped_container_type>>(_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<is_const_v<_SelfTy>, const_iterator, iterator>;
return _Maybe_const_iter{_STD move(_Key_it), _STD move(_Val_it)};
}

template <class _KeyTy>
_NODISCARD const_iterator _Upper_bound(const _KeyTy& _Key_val) const {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
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<const _MappedContainer>>(_Dist);
return const_iterator{_STD move(_Key_it), _STD move(_Val_it)};
template <class _SelfTy, class _KeyTy>
_NODISCARD auto _Lower_bound(this _SelfTy& _Self, const _KeyTy& _Key_val) {
return _Self._Find_bound(_Key_val, _RANGES lower_bound);
}

template <class _KeyTy>
_NODISCARD pair<iterator, iterator> _Equal_range(const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
return {lower_bound(_Key_val), upper_bound(_Key_val)};
template <class _SelfTy, class _KeyTy>
_NODISCARD auto _Upper_bound(this _SelfTy& _Self, const _KeyTy& _Key_val) {
return _Self._Find_bound(_Key_val, _RANGES upper_bound);
}

template <class _KeyTy>
_NODISCARD pair<const_iterator, const_iterator> _Equal_range(const _KeyTy& _Key_val) const {
template <class _SelfTy, class _KeyTy>
_NODISCARD auto _Equal_range(this _SelfTy& _Self, const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
return {lower_bound(_Key_val), upper_bound(_Key_val)};
return pair{_Self.lower_bound(_Key_val), _Self.upper_bound(_Key_val)};
}
};

Expand Down Expand Up @@ -1399,22 +1351,11 @@ private:
using _Mybase::_Key_equal;
using _Mybase::_Pass_key_comp;

template <class _KeyTy>
_NODISCARD mapped_type& _At(const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
const auto _Position = this->find(_Key_val);
if (_Position == this->end()) {
_Xout_of_range("invalid flat_map key");
}

return _Position->second;
}

template <class _KeyTy>
_NODISCARD const mapped_type& _At(const _KeyTy& _Key_val) const {
template <class _SelfTy, class _KeyTy>
_NODISCARD auto& _At(this _SelfTy& _Self, const _KeyTy& _Key_val) {
_STL_INTERNAL_STATIC_ASSERT(is_same_v<_KeyTy, key_type> || _Transparent<key_compare>);
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");
}

Expand Down
24 changes: 24 additions & 0 deletions tests/std/tests/P0429R9_flat_map/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,29 @@ void test_throwing_compare_swap() {
test_throwing_compare_swap_single<flat_multimap, deque, deque>();
}

// Test that changes in GH-5987 did not break calls of lookup member functions by using deducing this.
template <typename T>
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<flat_map<int, int>>();
test_lookup_call_on_temporaries_single<flat_multimap<int, int>>();
try {
(void) flat_map<int, int>{}.at(42);
(void) flat_map<int, int>{}.at('a');
} catch (...) {
}
}

int main() {
test_construction();
test_pointer_to_incomplete_type();
Expand All @@ -776,4 +799,5 @@ int main() {
test_insert_or_assign();
test_comparison();
test_throwing_compare_swap();
test_lookup_call_on_temporaries();
}
Loading