diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index 26def24f24e..1b9d9aae1a7 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -464,6 +464,23 @@ namespace __detail this->_M_incr(); return __tmp; } + +#if __cpp_impl_three_way_comparison >= 201907L + friend bool + operator==(const _Node_iterator&, const _Node_iterator&) = default; +#else + friend bool + operator==(const _Node_iterator& __x, const _Node_iterator& __y) noexcept + { + const __base_type& __bx = __x; + const __base_type& __by = __y; + return __bx == __by; + } + + friend bool + operator!=(const _Node_iterator& __x, const _Node_iterator& __y) noexcept + { return !(__x == __y); } +#endif }; /// Node const_iterators, used to iterate through all the hashtable. @@ -475,6 +492,10 @@ namespace __detail using __base_type = _Node_iterator_base<_Value, __cache>; using __node_type = typename __base_type::__node_type; + // The corresponding non-const iterator. + using __iterator + = _Node_iterator<_Value, __constant_iterators, __cache>; + public: typedef _Value value_type; typedef std::ptrdiff_t difference_type; @@ -489,8 +510,7 @@ namespace __detail _Node_const_iterator(__node_type* __p) noexcept : __base_type(__p) { } - _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators, - __cache>& __x) noexcept + _Node_const_iterator(const __iterator& __x) noexcept : __base_type(__x._M_cur) { } reference @@ -515,6 +535,62 @@ namespace __detail this->_M_incr(); return __tmp; } + +#if __cpp_impl_three_way_comparison >= 201907L + friend bool + operator==(const _Node_const_iterator&, + const _Node_const_iterator&) = default; + + friend bool + operator==(const _Node_const_iterator& __x, const __iterator& __y) + { + const __base_type& __bx = __x; + const __base_type& __by = __y; + return __bx == __by; + } +#else + friend bool + operator==(const _Node_const_iterator& __x, + const _Node_const_iterator& __y) noexcept + { + const __base_type& __bx = __x; + const __base_type& __by = __y; + return __bx == __by; + } + + friend bool + operator!=(const _Node_const_iterator& __x, + const _Node_const_iterator& __y) noexcept + { return !(__x == __y); } + + friend bool + operator==(const _Node_const_iterator& __x, + const __iterator& __y) noexcept + { + const __base_type& __bx = __x; + const __base_type& __by = __y; + return __bx == __by; + } + + friend bool + operator!=(const _Node_const_iterator& __x, + const __iterator& __y) noexcept + { return !(__x == __y); } + + friend bool + operator==(const __iterator& __x, + const _Node_const_iterator& __y) noexcept + { + const __base_type& __bx = __x; + const __base_type& __by = __y; + return __bx == __by; + } + + friend bool + operator!=(const __iterator& __x, + const _Node_const_iterator& __y) noexcept + { return !(__x == __y); } +#endif }; // Many of class template _Hashtable's template parameters are policy diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/115939.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/115939.cc new file mode 100644 index 00000000000..3a68acaff77 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/115939.cc @@ -0,0 +1,29 @@ +// { dg-options "-pedantic" } +// { dg-do compile { target c++11 } } + +// Bug 115939 - Cannot unambiguously compare iterators in std::unordered_map + +#include + +struct any_conv +{ + template + any_conv(T&&) { } + + template + friend bool operator==(const any_conv&, const T&) { return true; } + + template + friend bool operator!=(const any_conv&, const T&) { return false; } +}; + +std::unordered_map::iterator i{}; +std::unordered_map::const_iterator j{}; +bool b1 = i == i; // { dg-bogus "ambiguous" } +bool b2 = j == j; // { dg-bogus "ambiguous" } +bool b3 = i == j; // { dg-bogus "ambiguous" } +bool b4 = j == i; // { dg-bogus "ambiguous" } +bool b5 = i != i; // { dg-bogus "ambiguous" } +bool b6 = j != j; // { dg-bogus "ambiguous" } +bool b7 = i != j; // { dg-bogus "ambiguous" } +bool b8 = j != i; // { dg-bogus "ambiguous" }