@@ -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
new file mode 100644
@@ -0,0 +1,29 @@
+// { dg-options "-pedantic" }
+// { dg-do compile { target c++11 } }
+
+// Bug 115939 - Cannot unambiguously compare iterators in std::unordered_map
+
+#include <unordered_map>
+
+struct any_conv
+{
+ template<typename T>
+ any_conv(T&&) { }
+
+ template<typename T>
+ friend bool operator==(const any_conv&, const T&) { return true; }
+
+ template<typename T>
+ friend bool operator!=(const any_conv&, const T&) { return false; }
+};
+
+std::unordered_map<int, any_conv>::iterator i{};
+std::unordered_map<int, any_conv>::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" }