Make deque iterator operators hidden friends

Message ID c2589505-eafd-1881-a49d-4bd04ac9a03d@gmail.com
State New
Headers show
Series
  • Make deque iterator operators hidden friends
Related show

Commit Message

François Dumont May 8, 2019, 4:50 p.m.
Here is a patch to reduce number of operators exposed at std namespace 
scope.

     * include/bits/stl_deque.h
     (_Deque_iterator<>::operator+(difference_type)): Make hidden friend.
     (_Deque_iterator<>::operator-(difference_type)): Likewise.
     (operator==(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.
     (operator!=(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.
     (operator<(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.
     (operator<=(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.
     (operator>(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.
     (operator>=(const _Deque_iterator<>&, const _Deque_iterator<>&)):
     Likewise.

Tested under Linux x86_64 normal/debug modes.

Ok to commit ?

François

Comments

Jonathan Wakely May 8, 2019, 6:28 p.m. | #1
On 08/05/19 18:50 +0200, François Dumont wrote:
>Here is a patch to reduce number of operators exposed at std namespace 

>scope.

>

>    * include/bits/stl_deque.h

>    (_Deque_iterator<>::operator+(difference_type)): Make hidden friend.

>    (_Deque_iterator<>::operator-(difference_type)): Likewise.

>    (operator==(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>    (operator!=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>    (operator<(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>    (operator<=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>    (operator>(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>    (operator>=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>    Likewise.

>

>Tested under Linux x86_64 normal/debug modes.

>

>Ok to commit ?

>

>François

>


>diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h

>index 7a7a42aa903..72420c27646 100644

>--- a/libstdc++-v3/include/bits/stl_deque.h

>+++ b/libstdc++-v3/include/bits/stl_deque.h

>@@ -238,24 +238,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER

> 	return *this;

>       }

> 

>-      _Self

>-      operator+(difference_type __n) const _GLIBCXX_NOEXCEPT

>-      {

>-	_Self __tmp = *this;

>-	return __tmp += __n;

>-      }

>-

>       _Self&

>       operator-=(difference_type __n) _GLIBCXX_NOEXCEPT

>       { return *this += -__n; }

> 

>-      _Self

>-      operator-(difference_type __n) const _GLIBCXX_NOEXCEPT

>-      {

>-	_Self __tmp = *this;

>-	return __tmp -= __n;

>-      }

>-


These two are already not visible at namespace-scope, but it doesn't
hurt to make them hidden friends for consistency.

>+      friend _Self

>+      operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT

>+      {

>+	_Self __tmp = __x;

>+	return __tmp += __n;


I know you've just reused the original implementation, but it has a
problem that we might as well fix while touching t his code.

This function prevents NRVO copy elision, because __tmp += __n returns
a reference, which gets copied into the return value.

If you write it like this then the copy is elided, and __tmp is
constructed directly in the return value slot:

  _Self __tmp = __x;
  __tmp += __n;
  return __tmp;


>+      friend _Self

>+      operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT

>+      {

>+	_Self __tmp = __x;

>+	return __tmp -= __n;


Same problem here. It would be better to write:

  _Self __tmp = __x;
  __tmp -= __n;
  return __tmp;

OK for trunk with those two changes, thanks.
François Dumont May 9, 2019, 5:28 a.m. | #2
Thanks for the tip, nice to know.

Attached patch applied.

François

On 5/8/19 8:28 PM, Jonathan Wakely wrote:
> On 08/05/19 18:50 +0200, François Dumont wrote:

>> Here is a patch to reduce number of operators exposed at std 

>> namespace scope.

>>

>>     * include/bits/stl_deque.h

>>     (_Deque_iterator<>::operator+(difference_type)): Make hidden friend.

>>     (_Deque_iterator<>::operator-(difference_type)): Likewise.

>>     (operator==(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>     (operator!=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>     (operator<(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>     (operator<=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>     (operator>(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>     (operator>=(const _Deque_iterator<>&, const _Deque_iterator<>&)):

>>     Likewise.

>>

>> Tested under Linux x86_64 normal/debug modes.

>>

>> Ok to commit ?

>>

>> François

>>

>

>> diff --git a/libstdc++-v3/include/bits/stl_deque.h 

>> b/libstdc++-v3/include/bits/stl_deque.h

>> index 7a7a42aa903..72420c27646 100644

>> --- a/libstdc++-v3/include/bits/stl_deque.h

>> +++ b/libstdc++-v3/include/bits/stl_deque.h

>> @@ -238,24 +238,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER

>>     return *this;

>>       }

>>

>> -      _Self

>> -      operator+(difference_type __n) const _GLIBCXX_NOEXCEPT

>> -      {

>> -    _Self __tmp = *this;

>> -    return __tmp += __n;

>> -      }

>> -

>>       _Self&

>>       operator-=(difference_type __n) _GLIBCXX_NOEXCEPT

>>       { return *this += -__n; }

>>

>> -      _Self

>> -      operator-(difference_type __n) const _GLIBCXX_NOEXCEPT

>> -      {

>> -    _Self __tmp = *this;

>> -    return __tmp -= __n;

>> -      }

>> -

>

> These two are already not visible at namespace-scope, but it doesn't

> hurt to make them hidden friends for consistency.

>

>> +      friend _Self

>> +      operator+(const _Self& __x, difference_type __n) 

>> _GLIBCXX_NOEXCEPT

>> +      {

>> +    _Self __tmp = __x;

>> +    return __tmp += __n;

>

> I know you've just reused the original implementation, but it has a

> problem that we might as well fix while touching t his code.

>

> This function prevents NRVO copy elision, because __tmp += __n returns

> a reference, which gets copied into the return value.

>

> If you write it like this then the copy is elided, and __tmp is

> constructed directly in the return value slot:

>

>  _Self __tmp = __x;

>  __tmp += __n;

>  return __tmp;

>

>

>> +      friend _Self

>> +      operator-(const _Self& __x, difference_type __n) 

>> _GLIBCXX_NOEXCEPT

>> +      {

>> +    _Self __tmp = __x;

>> +    return __tmp -= __n;

>

> Same problem here. It would be better to write:

>

>  _Self __tmp = __x;

>  __tmp -= __n;

>  return __tmp;

>

> OK for trunk with those two changes, thanks.

>

>

>
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 7a7a42aa903..c050d1bf023 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -238,24 +238,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return *this;
       }
 
-      _Self
-      operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
-      {
-	_Self __tmp = *this;
-	return __tmp += __n;
-      }
-
       _Self&
       operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
       { return *this += -__n; }
 
-      _Self
-      operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
-      {
-	_Self __tmp = *this;
-	return __tmp -= __n;
-      }
-
       reference
       operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
       { return *(*this + __n); }
@@ -272,123 +258,118 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	_M_first = *__new_node;
 	_M_last = _M_first + difference_type(_S_buffer_size());
       }
-    };
-
-  // Note: we also provide overloads whose operands are of the same type in
-  // order to avoid ambiguous overload resolution when std::rel_ops operators
-  // are in scope (for additional details, see libstdc++/3628)
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return __x._M_cur == __y._M_cur; }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return __x._M_cur == __y._M_cur; }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x == __y); }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x == __y); }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
-					  : (__x._M_node < __y._M_node); }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
-					  : (__x._M_node < __y._M_node); }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return __y < __x; }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return __y < __x; }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__y < __x); }
+      friend bool
+      operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return __x._M_cur == __y._M_cur; }
+
+      // Note: we also provide overloads whose operands are of the same type in
+      // order to avoid ambiguous overload resolution when std::rel_ops operators
+      // are in scope (for additional details, see libstdc++/3628)
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator==(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return __x._M_cur == __y._M_cur; }
+
+      friend bool
+      operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__x == __y); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator!=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__x == __y); }
+
+      friend bool
+      operator<(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      {
+	return (__x._M_node == __y._M_node)
+	  ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__y < __x); }
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator<(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{
+	  return (__x._M_node == __y._M_node)
+	    ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
+	}
 
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x < __y); }
+      friend bool
+      operator>(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return __y < __x; }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator>(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return __y < __x; }
+
+      friend bool
+      operator<=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__y < __x); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator<=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__y < __x); }
+
+      friend bool
+      operator>=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__x < __y); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator>=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__x < __y); }
+
+      friend difference_type
+      operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      {
+	return difference_type(_S_buffer_size())
+	  * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
+	  + (__y._M_last - __y._M_cur);
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x < __y); }
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // According to the resolution of DR179 not only the various comparison
+      // operators but also operator- must accept mixed iterator/const_iterator
+      // parameters.
+      template<typename _RefR, typename _PtrR>
+	friend difference_type
+	operator-(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{
+	  return difference_type(_S_buffer_size())
+	    * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
+	    + (__y._M_last - __y._M_cur);
+	}
 
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // According to the resolution of DR179 not only the various comparison
-  // operators but also operator- must accept mixed iterator/const_iterator
-  // parameters.
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
-    operator-(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    {
-      return typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
-	(_Deque_iterator<_Tp, _Ref, _Ptr>::_S_buffer_size())
-	* (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
-	+ (__y._M_last - __y._M_cur);
-    }
+      friend _Self
+      operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
+      {
+	_Self __tmp = __x;
+	__tmp += __n;
+	return __tmp;
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
-    operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    {
-      return typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
-	(_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size())
-	* (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
-	+ (__y._M_last - __y._M_cur);
-    }
+      friend _Self
+      operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
+      {
+	_Self __tmp = __x;
+	__tmp -= __n;
+	return __tmp;
+      }
 
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline _Deque_iterator<_Tp, _Ref, _Ptr>
-    operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
-    _GLIBCXX_NOEXCEPT
-    { return __x + __n; }
+      friend _Self
+      operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
+      { return __x + __n; }
+    };
 
   /**
    *  Deque base class.  This class provides the unified face for %deque's
@@ -2234,8 +2215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   */
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator==(const deque<_Tp, _Alloc>& __x,
-                         const deque<_Tp, _Alloc>& __y)
+    operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return __x.size() == __y.size()
 	     && std::equal(__x.begin(), __x.end(), __y.begin()); }
 
@@ -2252,37 +2232,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   */
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator<(const deque<_Tp, _Alloc>& __x,
-	      const deque<_Tp, _Alloc>& __y)
+    operator<(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return std::lexicographical_compare(__x.begin(), __x.end(),
 					  __y.begin(), __y.end()); }
 
   /// Based on operator==
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator!=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator!=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__x == __y); }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator>(const deque<_Tp, _Alloc>& __x,
-	      const deque<_Tp, _Alloc>& __y)
+    operator>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return __y < __x; }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator<=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator<=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__y < __x); }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator>=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__x < __y); }
 
   /// See std::deque::swap().

Patch

diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 7a7a42aa903..72420c27646 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -238,24 +238,10 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	return *this;
       }
 
-      _Self
-      operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
-      {
-	_Self __tmp = *this;
-	return __tmp += __n;
-      }
-
       _Self&
       operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
       { return *this += -__n; }
 
-      _Self
-      operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
-      {
-	_Self __tmp = *this;
-	return __tmp -= __n;
-      }
-
       reference
       operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
       { return *(*this + __n); }
@@ -272,123 +258,116 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	_M_first = *__new_node;
 	_M_last = _M_first + difference_type(_S_buffer_size());
       }
-    };
-
-  // Note: we also provide overloads whose operands are of the same type in
-  // order to avoid ambiguous overload resolution when std::rel_ops operators
-  // are in scope (for additional details, see libstdc++/3628)
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return __x._M_cur == __y._M_cur; }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return __x._M_cur == __y._M_cur; }
 
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x == __y); }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x == __y); }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
-					  : (__x._M_node < __y._M_node); }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
-					  : (__x._M_node < __y._M_node); }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return __y < __x; }
-
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return __y < __x; }
-
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__y < __x); }
+      friend bool
+      operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return __x._M_cur == __y._M_cur; }
+
+      // Note: we also provide overloads whose operands are of the same type in
+      // order to avoid ambiguous overload resolution when std::rel_ops operators
+      // are in scope (for additional details, see libstdc++/3628)
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator==(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return __x._M_cur == __y._M_cur; }
+
+      friend bool
+      operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__x == __y); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator!=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__x == __y); }
+
+      friend bool
+      operator<(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      {
+	return (__x._M_node == __y._M_node)
+	  ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__y < __x); }
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator<(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{
+	  return (__x._M_node == __y._M_node)
+	    ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
+	}
 
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline bool
-    operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	       const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x < __y); }
+      friend bool
+      operator>(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return __y < __x; }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator>(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return __y < __x; }
+
+      friend bool
+      operator<=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__y < __x); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator<=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__y < __x); }
+
+      friend bool
+      operator>=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      { return !(__x < __y); }
+
+      template<typename _RefR, typename _PtrR>
+	friend bool
+	operator>=(const _Self& __x,
+		   const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{ return !(__x < __y); }
+
+      friend difference_type
+      operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
+      {
+	return difference_type(_S_buffer_size())
+	  * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
+	  + (__y._M_last - __y._M_cur);
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline bool
-    operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	       const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    { return !(__x < __y); }
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // According to the resolution of DR179 not only the various comparison
+      // operators but also operator- must accept mixed iterator/const_iterator
+      // parameters.
+      template<typename _RefR, typename _PtrR>
+	friend difference_type
+	operator-(const _Self& __x,
+		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+	{
+	  return difference_type(_S_buffer_size())
+	    * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
+	    + (__y._M_last - __y._M_cur);
+	}
 
-  // _GLIBCXX_RESOLVE_LIB_DEFECTS
-  // According to the resolution of DR179 not only the various comparison
-  // operators but also operator- must accept mixed iterator/const_iterator
-  // parameters.
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
-    operator-(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
-	      const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
-    {
-      return typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
-	(_Deque_iterator<_Tp, _Ref, _Ptr>::_S_buffer_size())
-	* (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
-	+ (__y._M_last - __y._M_cur);
-    }
+      friend _Self
+      operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
+      {
+	_Self __tmp = __x;
+	return __tmp += __n;
+      }
 
-  template<typename _Tp, typename _RefL, typename _PtrL,
-	   typename _RefR, typename _PtrR>
-    inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
-    operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
-	      const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
-    {
-      return typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
-	(_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size())
-	* (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
-	+ (__y._M_last - __y._M_cur);
-    }
+      friend _Self
+      operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
+      {
+	_Self __tmp = __x;
+	return __tmp -= __n;
+      }
 
-  template<typename _Tp, typename _Ref, typename _Ptr>
-    inline _Deque_iterator<_Tp, _Ref, _Ptr>
-    operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
-    _GLIBCXX_NOEXCEPT
-    { return __x + __n; }
+      friend _Self
+      operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
+      { return __x + __n; }
+    };
 
   /**
    *  Deque base class.  This class provides the unified face for %deque's
@@ -2252,37 +2231,32 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   */
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator<(const deque<_Tp, _Alloc>& __x,
-	      const deque<_Tp, _Alloc>& __y)
+    operator<(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return std::lexicographical_compare(__x.begin(), __x.end(),
 					  __y.begin(), __y.end()); }
 
   /// Based on operator==
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator!=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator!=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__x == __y); }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator>(const deque<_Tp, _Alloc>& __x,
-	      const deque<_Tp, _Alloc>& __y)
+    operator>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return __y < __x; }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator<=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator<=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__y < __x); }
 
   /// Based on operator<
   template<typename _Tp, typename _Alloc>
     inline bool
-    operator>=(const deque<_Tp, _Alloc>& __x,
-	       const deque<_Tp, _Alloc>& __y)
+    operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
     { return !(__x < __y); }
 
   /// See std::deque::swap().