[PATCH] Cleanup compiler diagnostics

François Dumont frs.dumont@gmail.com
Mon Sep 16 05:07:23 GMT 2024


Hi

Before I extend those changes to the whole library I'd like to know if 
there is any interest in this effort.

Thanks to this patch build of the new test cases simply gives:

~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc: In 
function 'int main()':
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:17: 
error: no match for 'operator==' in 's1 == s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:18: 
error: no match for 'operator<' in 's1 < s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:19: 
error: no match for 'operator!=' in 's1 != s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:20: 
error: no match for 'operator>' in 's1 > s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:21: 
error: no match for 'operator<=' in 's1 <= s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:22: 
error: no match for 'operator>=' in 's1 >= s2' (operand types are 
'NoOperators' and 'NoOperators')
~/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc:23: 
error: no match for 'operator<=>' in 's1 <=> s2' (operand types are 
'NoOperators' and 'NoOperators')

and not 2 or more screens of potential candidates that does not match 
because of template deduction issues.

Of course if I include stdc++.h it is more 5 screens.

If there is interest some questions before I submit this patch properly:

Where to put the new tests ?

Anyone to help making those test FAIL rather than XFAIL if there is for 
example any 'note: candidate' in the output ?

I also tried to deal with spaceship operator in this patch. But it has 
side effect because __synth3way_t is not SFINAE friendly. There is this 
problem in 23_containers/vector/cmp_c++20.cc:

Excess errors:
~/gcc/git/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc:126: 
error: static assertion failed
~/gcc/git/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc:129: 
error: no match for 'operator<=>' in 'c <=> c' (operand types are 
'std::vector<test04()::L>' and 'std::vector<test04()::L>')

It's due to three_way_comparable<> not doing the same job as _Synth3way 
for type having only a '<' operator. Should it ?

François
-------------- next part --------------
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 9e75b37fce7..f7200fa0574 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -221,30 +221,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return false; }
 #endif
 
-      // Inherit everything else.
-    };
-
       /** Equality comparison for std::allocator objects
        *
        * @return true, for all std::allocator objects.
        * @relates std::allocator
        */
-  template<typename _T1, typename _T2>
+      template<typename _T2>
 	__attribute__((__always_inline__))
-    inline _GLIBCXX20_CONSTEXPR bool
-    operator==(const allocator<_T1>&, const allocator<_T2>&)
+	friend inline _GLIBCXX20_CONSTEXPR bool
+	operator==(const allocator&, const allocator<_T2>&)
 	_GLIBCXX_NOTHROW
 	{ return true; }
 
 #if __cpp_impl_three_way_comparison < 201907L
-  template<typename _T1, typename _T2>
+      template<typename _T2>
 	__attribute__((__always_inline__))
-    inline _GLIBCXX20_CONSTEXPR bool
-    operator!=(const allocator<_T1>&, const allocator<_T2>&)
+	friend inline _GLIBCXX20_CONSTEXPR bool
+	operator!=(const allocator&, const allocator<_T2>&)
 	_GLIBCXX_NOTHROW
 	{ return false; }
 #endif
 
+      // Inherit everything else.
+    };
+
   /// @cond undocumented
 
   // Invalid allocator<cv T> partial specializations.
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index e7e352020d5..3dc9a59577e 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -1071,22 +1071,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 		      string_type>
 	_M_str() const
 	{ return str(); }
-    };
-
-
-  /** @brief Standard regex submatch over a C-style null-terminated string. */
-  typedef sub_match<const char*>	     csub_match;
-
-  /** @brief Standard regex submatch over a standard string. */
-  typedef sub_match<string::const_iterator>  ssub_match;
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  /** @brief Regex submatch over a C-style null-terminated wide string. */
-  typedef sub_match<const wchar_t*>	  wcsub_match;
-
-  /** @brief Regex submatch over a standard wide string. */
-  typedef sub_match<wstring::const_iterator> wssub_match;
-#endif
 
       // [7.9.2] sub_match non-member operators
 
@@ -1098,9 +1082,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs  is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator==(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator==(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) == 0; }
 
 #if __cpp_lib_three_way_comparison
@@ -1111,10 +1094,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @returns A value indicating whether `__lhs` is less than, equal to,
        *	      greater than, or incomparable with `__rhs`.
        */
-  template<typename _BiIter>
-    inline auto
-    operator<=>(const sub_match<_BiIter>& __lhs,
-		const sub_match<_BiIter>& __rhs)
+      friend inline auto
+      operator<=>(const sub_match& __lhs, const sub_match& __rhs)
       noexcept(__detail::__is_contiguous_iter<_BiIter>::value)
       {
 	using _Tr = char_traits<typename iterator_traits<_BiIter>::value_type>;
@@ -1127,9 +1108,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs  is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator!=(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator!=(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) != 0; }
 
       /**
@@ -1138,9 +1118,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator<(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator<(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) < 0; }
 
       /**
@@ -1149,9 +1128,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator<=(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator<=(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) <= 0; }
 
       /**
@@ -1160,9 +1138,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator>=(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator>=(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) >= 0; }
 
       /**
@@ -1171,19 +1148,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs Second regular expression submatch.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _BiIter>
-    inline bool
-    operator>(const sub_match<_BiIter>& __lhs, const sub_match<_BiIter>& __rhs)
+      friend inline bool
+      operator>(const sub_match& __lhs, const sub_match& __rhs)
       { return __lhs.compare(__rhs) > 0; }
 #endif // three-way comparison
 
       /// @cond undocumented
 
       // Alias for a basic_string that can be compared to a sub_match.
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    using __sub_match_string = basic_string<
-			      typename iterator_traits<_Bi_iter>::value_type,
-			      _Ch_traits, _Ch_alloc>;
+      template<typename _Ch_traits, typename _Ch_alloc>
+	using __sub_match_string =
+	  basic_string<value_type, _Ch_traits, _Ch_alloc>;
       /// @endcond
 
 #if ! __cpp_lib_three_way_comparison
@@ -1194,10 +1169,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs  is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator==(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator==(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		   const sub_match& __rhs)
 	{ return __rhs._M_compare(__lhs.data(), __lhs.size()) == 0; }
 
       /**
@@ -1207,10 +1182,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs  is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator!=(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator!=(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		   const sub_match& __rhs)
 	{ return !(__lhs == __rhs); }
 
       /**
@@ -1219,10 +1194,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator<(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator<(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		  const sub_match& __rhs)
 	{ return __rhs._M_compare(__lhs.data(), __lhs.size()) > 0; }
 
       /**
@@ -1231,10 +1206,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator>(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator>(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		  const sub_match& __rhs)
 	{ return __rhs < __lhs; }
 
       /**
@@ -1243,10 +1218,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator>=(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator>=(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		   const sub_match& __rhs)
 	{ return !(__lhs < __rhs); }
 
       /**
@@ -1255,10 +1230,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator<=(const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator<=(const __sub_match_string<_Ch_traits, _Ch_alloc>& __lhs,
+		   const sub_match& __rhs)
 	{ return !(__rhs < __lhs); }
 #endif // three-way comparison
 
@@ -1269,10 +1244,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator==(const sub_match<_Bi_iter>& __lhs,
-	       const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator==(const sub_match& __lhs,
+		   const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return __lhs._M_compare(__rhs.data(), __rhs.size()) == 0; }
 
 #if __cpp_lib_three_way_comparison
@@ -1283,14 +1258,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @returns A value indicating whether `__lhs` is less than, equal to,
        *	      greater than, or incomparable with `__rhs`.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Alloc>
-    inline auto
-    operator<=>(const sub_match<_Bi_iter>& __lhs,
-		const __sub_match_string<_Bi_iter, _Ch_traits, _Alloc>& __rhs)
-    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+      template<typename _Ch_traits, typename _Alloc>
+	friend inline auto
+	operator<=>(const sub_match& __lhs,
+		    const __sub_match_string<_Ch_traits, _Alloc>& __rhs)
+	noexcept(__detail::__is_contiguous_iter<_BiIter>::value)
 	{
-      return __detail::__char_traits_cmp_cat<_Ch_traits>(
-	  __lhs._M_compare(__rhs.data(), __rhs.size()));
+	  return __detail::__char_traits_cmp_cat<_Ch_traits>
+	    (__lhs._M_compare(__rhs.data(), __rhs.size()));
 	}
 #else
       /**
@@ -1300,10 +1275,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator!=(const sub_match<_Bi_iter>& __lhs,
-	       const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator!=(const sub_match& __lhs,
+		   const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return !(__lhs == __rhs); }
 
       /**
@@ -1312,10 +1287,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator<(const sub_match<_Bi_iter>& __lhs,
-	      const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator<(const sub_match& __lhs,
+		  const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return __lhs._M_compare(__rhs.data(), __rhs.size()) < 0; }
 
       /**
@@ -1324,10 +1299,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator>(const sub_match<_Bi_iter>& __lhs,
-	      const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator>(const sub_match& __lhs,
+		  const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return __rhs < __lhs; }
 
       /**
@@ -1336,10 +1311,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator>=(const sub_match<_Bi_iter>& __lhs,
-	       const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	 operator>=(const sub_match& __lhs,
+		    const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return !(__lhs < __rhs); }
 
       /**
@@ -1348,10 +1323,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A string.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter, typename _Ch_traits, typename _Ch_alloc>
-    inline bool
-    operator<=(const sub_match<_Bi_iter>& __lhs,
-	       const __sub_match_string<_Bi_iter, _Ch_traits, _Ch_alloc>& __rhs)
+      template<typename _Ch_traits, typename _Ch_alloc>
+	friend inline bool
+	operator<=(const sub_match& __lhs,
+		   const __sub_match_string<_Ch_traits, _Ch_alloc>& __rhs)
 	{ return !(__rhs < __lhs); }
 
       /**
@@ -1361,10 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs  is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator==(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator==(value_type const* __lhs, const sub_match& __rhs)
       { return __rhs.compare(__lhs) == 0; }
 
       /**
@@ -1374,10 +1347,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator!=(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator!=(value_type const* __lhs, const sub_match& __rhs)
       { return !(__lhs == __rhs); }
 
       /**
@@ -1386,10 +1357,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator<(value_type const* __lhs, const sub_match& __rhs)
       { return __rhs.compare(__lhs) > 0; }
 
       /**
@@ -1398,10 +1367,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator>(value_type const* __lhs, const sub_match& __rhs)
       { return __rhs < __lhs; }
 
       /**
@@ -1410,10 +1377,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>=(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator>=(value_type const* __lhs, const sub_match& __rhs)
       { return !(__lhs < __rhs); }
 
       /**
@@ -1422,10 +1387,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<=(typename iterator_traits<_Bi_iter>::value_type const* __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator<=(value_type const* __lhs, const sub_match& __rhs)
       { return !(__rhs < __lhs); }
 #endif // three-way comparison
 
@@ -1436,10 +1399,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs  is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator==(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator==(const sub_match& __lhs, value_type const* __rhs)
       { return __lhs.compare(__rhs) == 0; }
 
 #if __cpp_lib_three_way_comparison
@@ -1451,13 +1412,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @returns A value indicating whether `__lhs` is less than, equal to,
        *	      greater than, or incomparable with `__rhs`.
        */
-  template<typename _Bi_iter>
-    inline auto
-    operator<=>(const sub_match<_Bi_iter>& __lhs,
-		typename iterator_traits<_Bi_iter>::value_type const* __rhs)
-    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+      friend inline auto
+      operator<=>(const sub_match& __lhs, value_type const* __rhs)
+      noexcept(__detail::__is_contiguous_iter<_BiIter>::value)
       {
-      using _Tr = char_traits<typename iterator_traits<_Bi_iter>::value_type>;
+	using _Tr = char_traits<value_type>;
 	return __detail::__char_traits_cmp_cat<_Tr>(__lhs.compare(__rhs));
       }
 #else
@@ -1468,10 +1427,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator!=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator!=(const sub_match& __lhs, value_type const* __rhs)
       { return !(__lhs == __rhs); }
 
       /**
@@ -1480,10 +1437,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<(const sub_match<_Bi_iter>& __lhs,
-	      typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator<(const sub_match& __lhs, value_type const* __rhs)
       { return __lhs.compare(__rhs) < 0; }
 
       /**
@@ -1492,10 +1447,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>(const sub_match<_Bi_iter>& __lhs,
-	      typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator>(const sub_match& __lhs, value_type const* __rhs)
       { return __rhs < __lhs; }
 
       /**
@@ -1504,10 +1457,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator>=(const sub_match& __lhs, value_type const* __rhs)
       { return !(__lhs < __rhs); }
 
       /**
@@ -1516,10 +1467,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A null-terminated string.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const* __rhs)
+      friend inline bool
+      operator<=(const sub_match& __lhs, value_type const* __rhs)
       { return !(__rhs < __lhs); }
 
       /**
@@ -1529,10 +1478,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator==(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator==(value_type const& __lhs, const sub_match& __rhs)
       { return __rhs._M_compare(std::__addressof(__lhs), 1) == 0; }
 
       /**
@@ -1542,10 +1489,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator!=(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator!=(value_type const& __lhs, const sub_match& __rhs)
       { return !(__lhs == __rhs); }
 
       /**
@@ -1555,10 +1500,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator<(value_type const& __lhs, const sub_match& __rhs)
       { return __rhs._M_compare(std::__addressof(__lhs), 1) > 0; }
 
       /**
@@ -1568,10 +1511,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	      const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator>(value_type const& __lhs, const sub_match& __rhs)
       { return __rhs < __lhs; }
 
       /**
@@ -1581,10 +1522,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>=(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator>=(value_type const& __lhs, const sub_match& __rhs)
       { return !(__lhs < __rhs); }
 
       /**
@@ -1594,10 +1533,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A regular expression submatch.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<=(typename iterator_traits<_Bi_iter>::value_type const& __lhs,
-	       const sub_match<_Bi_iter>& __rhs)
+      friend inline bool
+      operator<=(value_type const& __lhs, const sub_match& __rhs)
       { return !(__rhs < __lhs); }
 #endif // three-way comparison
 
@@ -1608,10 +1545,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs  is equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator==(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator==(const sub_match& __lhs, value_type const& __rhs)
       { return __lhs._M_compare(std::__addressof(__rhs), 1) == 0; }
 
 #if __cpp_lib_three_way_comparison
@@ -1623,16 +1558,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @returns A value indicating whether `__lhs` is less than, equal to,
        *	      greater than, or incomparable with `__rhs`.
        */
-
-  template<typename _Bi_iter>
-    inline auto
-    operator<=>(const sub_match<_Bi_iter>& __lhs,
-		typename iterator_traits<_Bi_iter>::value_type const& __rhs)
-    noexcept(__detail::__is_contiguous_iter<_Bi_iter>::value)
+      friend inline auto
+      operator<=>(const sub_match& __lhs, value_type const& __rhs)
+      noexcept(__detail::__is_contiguous_iter<_BiIter>::value)
       {
-      using _Tr = char_traits<typename iterator_traits<_Bi_iter>::value_type>;
-      return __detail::__char_traits_cmp_cat<_Tr>(
-	  __lhs._M_compare(std::__addressof(__rhs), 1));
+	using _Tr = char_traits<value_type>;
+	return __detail::__char_traits_cmp_cat<_Tr>
+	  (__lhs._M_compare(std::__addressof(__rhs), 1));
       }
 #else
       /**
@@ -1642,10 +1574,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs is not equivalent to @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator!=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator!=(const sub_match& __lhs, value_type const& __rhs)
       { return !(__lhs == __rhs); }
 
       /**
@@ -1655,10 +1585,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs precedes @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<(const sub_match<_Bi_iter>& __lhs,
-	      typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator<(const sub_match& __lhs, value_type const& __rhs)
       { return __lhs._M_compare(std::__addressof(__rhs), 1) < 0; }
 
       /**
@@ -1668,10 +1596,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs succeeds @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>(const sub_match<_Bi_iter>& __lhs,
-	      typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator>(const sub_match& __lhs, value_type const& __rhs)
       { return __rhs < __lhs; }
 
       /**
@@ -1681,10 +1607,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs does not precede @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator>=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator>=(const sub_match& __lhs, value_type const& __rhs)
       { return !(__lhs < __rhs); }
 
       /**
@@ -1694,10 +1618,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __rhs A character.
        * @returns true if @a __lhs does not succeed @a __rhs, false otherwise.
        */
-  template<typename _Bi_iter>
-    inline bool
-    operator<=(const sub_match<_Bi_iter>& __lhs,
-	       typename iterator_traits<_Bi_iter>::value_type const& __rhs)
+      friend inline bool
+      operator<=(const sub_match& __lhs, value_type const& __rhs)
       { return !(__rhs < __lhs); }
 #endif // three-way comparison
 
@@ -1709,14 +1631,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *
        * @returns the output stream with the submatch string inserted.
        */
-  template<typename _Ch_type, typename _Ch_traits, typename _Bi_iter>
-    inline
+      template<typename _Ch_type, typename _Ch_traits>
+	friend inline
 	basic_ostream<_Ch_type, _Ch_traits>&
 	operator<<(basic_ostream<_Ch_type, _Ch_traits>& __os,
-	       const sub_match<_Bi_iter>& __m)
+		   const sub_match& __m)
 	{ return __os << __m.str(); }
 
       /// @} relates sub_match
+    };
+
+
+  /** @brief Standard regex submatch over a C-style null-terminated string. */
+  typedef sub_match<const char*>	     csub_match;
+
+  /** @brief Standard regex submatch over a standard string. */
+  typedef sub_match<string::const_iterator>  ssub_match;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  /** @brief Regex submatch over a C-style null-terminated wide string. */
+  typedef sub_match<const wchar_t*>	  wcsub_match;
+
+  /** @brief Regex submatch over a standard wide string. */
+  typedef sub_match<wstring::const_iterator> wssub_match;
+#endif
 
   // [7.10] Class template match_results
 
@@ -2163,14 +2101,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 
       _Bi_iter _M_begin {};
       /// @endcond
-    };
-
-  typedef match_results<const char*>		 cmatch;
-  typedef match_results<string::const_iterator>	 smatch;
-#ifdef _GLIBCXX_USE_WCHAR_T
-  typedef match_results<const wchar_t*>		 wcmatch;
-  typedef match_results<wstring::const_iterator> wsmatch;
-#endif
 
       // match_results comparisons
 
@@ -2181,10 +2111,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *
        * @relates match_results
        */
-  template<typename _Bi_iter, typename _Alloc>
-    inline bool
-    operator==(const match_results<_Bi_iter, _Alloc>& __m1,
-	       const match_results<_Bi_iter, _Alloc>& __m2)
+      friend inline bool
+      operator==(const match_results& __m1, const match_results& __m2)
       {
 	if (__m1.ready() != __m2.ready())
 	  return false;
@@ -2208,12 +2136,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *
        * @relates match_results
        */
-  template<typename _Bi_iter, class _Alloc>
-    inline bool
-    operator!=(const match_results<_Bi_iter, _Alloc>& __m1,
-	       const match_results<_Bi_iter, _Alloc>& __m2)
+      friend inline bool
+      operator!=(const match_results& __m1, const match_results& __m2)
       { return !(__m1 == __m2); }
 #endif
+    };
+
+  typedef match_results<const char*>		 cmatch;
+  typedef match_results<string::const_iterator>	 smatch;
+#ifdef _GLIBCXX_USE_WCHAR_T
+  typedef match_results<const wchar_t*>		 wcmatch;
+  typedef match_results<wstring::const_iterator> wsmatch;
+#endif
 
   // [7.10.6] match_results swap
   /**
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 42261ac5915..07f82c5c23c 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -1584,6 +1584,80 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #else
       void data() { }
 #endif
+
+      /**
+       *  @brief  Vector equality comparison.
+       *  @param  __x  A %vector.
+       *  @param  __y  A %vector of the same type as @a __x.
+       *  @return  True iff the size and elements of the vectors are equal.
+       *
+       *  This is an equivalence relation.  It is linear in the size of the
+       *  vectors.  Vectors are considered equivalent if their sizes are equal,
+       *  and if corresponding elements compare equal.
+       */
+      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
+      friend inline bool
+      operator==(const vector& __x, const vector& __y)
+      { return (__x.size() == __y.size()
+		&& std::equal(__x.begin(), __x.end(), __y.begin())); }
+
+#if __cpp_lib_three_way_comparison
+      /**
+       *  @brief  Vector ordering relation.
+       *  @param  __x  A `vector`.
+       *  @param  __y  A `vector` of the same type as `__x`.
+       *  @return  A value indicating whether `__x` is less than, equal to,
+       *           greater than, or incomparable with `__y`.
+       *
+       *  See `std::lexicographical_compare_three_way()` for how the determination
+       *  is made. This operator is used to synthesize relational operators like
+       *  `<` and `>=` etc.
+       */
+      [[nodiscard]] _GLIBCXX20_CONSTEXPR
+      friend inline __detail::__synth3way_t<bool>
+      operator<=>(const vector& __x, const vector& __y)
+      {
+	return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+						      __y.begin(), __y.end(),
+						      __detail::__synth3way);
+      }
+#else
+      /**
+       *  @brief  Vector ordering relation.
+       *  @param  __x  A %vector.
+       *  @param  __y  A %vector of the same type as @a __x.
+       *  @return  True iff @a __x is lexicographically less than @a __y.
+       *
+       *  This is a total ordering relation.  It is linear in the size of the
+       *  vectors.  The elements must be comparable with @c <.
+       *
+       *  See std::lexicographical_compare() for how the determination is made.
+       */
+      _GLIBCXX_NODISCARD friend inline bool
+      operator<(const vector& __x, const vector& __y)
+      { return std::lexicographical_compare(__x.begin(), __x.end(),
+					    __y.begin(), __y.end()); }
+
+      /// Based on operator==
+      _GLIBCXX_NODISCARD friend inline bool
+      operator!=(const vector& __x, const vector& __y)
+      { return !(__x == __y); }
+
+      /// Based on operator<
+      _GLIBCXX_NODISCARD friend inline bool
+      operator>(const vector& __x, const vector& __y)
+      { return __y < __x; }
+
+      /// Based on operator<
+      _GLIBCXX_NODISCARD friend inline bool
+      operator<=(const vector& __x, const vector& __y)
+      { return !(__y < __x); }
+
+      /// Based on operator<
+      _GLIBCXX_NODISCARD friend inline bool
+      operator>=(const vector& __x, const vector& __y)
+      { return !(__x < __y); }
+#endif // three-way comparison
     };
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 20c0319f3a7..20aa820cb78 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -422,7 +422,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	static _GLIBCXX17_CONSTEXPR pointer
 	_S_to_pointer(_Tp __t)
         { return __t.operator->(); }
-    };
 
       ///@{
       /**
@@ -435,198 +434,173 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *
       */
 #if __cplusplus <= 201703L || ! defined __glibcxx_concepts
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator==(const reverse_iterator<_Iterator>& __x,
-	       const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator==(const reverse_iterator& __x, const reverse_iterator& __y)
       { return __x.base() == __y.base(); }
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<(const reverse_iterator<_Iterator>& __x,
-	      const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator<(const reverse_iterator& __x, const reverse_iterator& __y)
       { return __y.base() < __x.base(); }
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator!=(const reverse_iterator<_Iterator>& __x,
-	       const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator!=(const reverse_iterator& __x, const reverse_iterator& __y)
       { return !(__x == __y); }
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>(const reverse_iterator<_Iterator>& __x,
-	      const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator>(const reverse_iterator& __x, const reverse_iterator& __y)
       { return __y < __x; }
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<=(const reverse_iterator<_Iterator>& __x,
-	       const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator<=(const reverse_iterator& __x, const reverse_iterator& __y)
       { return !(__y < __x); }
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>=(const reverse_iterator<_Iterator>& __x,
-	       const reverse_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator>=(const reverse_iterator& __x, const reverse_iterator& __y)
       { return !(__x < __y); }
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 280. Comparison of reverse_iterator to const reverse_iterator.
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	_GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator==(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator==(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() == __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	_GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator<(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() > __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	_GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator!=(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator!=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() != __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	_GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator>(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() < __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<=(const reverse_iterator<_IteratorL>& __x,
+      template<typename _IteratorR>
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator<=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() >= __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	_GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>=(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator>=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	{ return __x.base() <= __y.base(); }
 #else // C++20
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator==(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator==(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() == __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator!=(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator!=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() != __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() != __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator<(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator<(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() > __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() > __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator>(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator>(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() < __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator<=(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator<=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() >= __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() >= __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[nodiscard]]
-    constexpr bool
-    operator>=(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr bool
+	operator>=(const reverse_iterator& __x,
 		   const reverse_iterator<_IteratorR>& __y)
 	requires requires { { __x.base() <= __y.base() } -> convertible_to<bool>; }
 	{ return __x.base() <= __y.base(); }
 
-  template<typename _IteratorL,
-	   three_way_comparable_with<_IteratorL> _IteratorR>
+      template<three_way_comparable_with<_Iterator> _IteratorR>
 	[[nodiscard]]
-    constexpr compare_three_way_result_t<_IteratorL, _IteratorR>
-    operator<=>(const reverse_iterator<_IteratorL>& __x,
+	friend constexpr compare_three_way_result_t<_Iterator, _IteratorR>
+	operator<=>(const reverse_iterator& __x,
 		    const reverse_iterator<_IteratorR>& __y)
 	{ return __y.base() <=> __x.base(); }
 
       // Additional, non-standard overloads to avoid ambiguities with greedy,
       // unconstrained overloads in associated namespaces.
 
-  template<typename _Iterator>
       [[nodiscard]]
-    constexpr bool
-    operator==(const reverse_iterator<_Iterator>& __x,
-	       const reverse_iterator<_Iterator>& __y)
+      friend constexpr bool
+      operator==(const reverse_iterator& __x, const reverse_iterator& __y)
       requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; }
       { return __x.base() == __y.base(); }
-
-  template<three_way_comparable _Iterator>
-    [[nodiscard]]
-    constexpr compare_three_way_result_t<_Iterator, _Iterator>
-    operator<=>(const reverse_iterator<_Iterator>& __x,
-		const reverse_iterator<_Iterator>& __y)
-    { return __y.base() <=> __x.base(); }
 #endif // C++20
   ///@}
 
 #if __cplusplus < 201103L
-  template<typename _Iterator>
-    inline typename reverse_iterator<_Iterator>::difference_type
-    operator-(const reverse_iterator<_Iterator>& __x,
-	      const reverse_iterator<_Iterator>& __y)
+      friend inline difference_type
+      operator-(const reverse_iterator& __x, const reverse_iterator& __y)
       { return __y.base() - __x.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
-    inline typename reverse_iterator<_IteratorL>::difference_type
-    operator-(const reverse_iterator<_IteratorL>& __x,
+      template<typename _IteratorR>
+	friend inline difference_type
+	operator-(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	{ return __y.base() - __x.base(); }
 #else
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 685. reverse_iterator/move_iterator difference has invalid signatures
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR auto
-    operator-(const reverse_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR auto
+	operator-(const reverse_iterator& __x,
 		  const reverse_iterator<_IteratorR>& __y)
 	-> decltype(__y.base() - __x.base())
 	{ return __y.base() - __x.base(); }
 #endif
 
-  template<typename _Iterator>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator>
-    operator+(typename reverse_iterator<_Iterator>::difference_type __n,
-	      const reverse_iterator<_Iterator>& __x)
-    { return reverse_iterator<_Iterator>(__x.base() - __n); }
+      friend inline _GLIBCXX17_CONSTEXPR reverse_iterator
+      operator+(difference_type __n, const reverse_iterator& __x)
+      { return reverse_iterator(__x.base() - __n); }
+    };
 
 #if __cplusplus >= 201103L
   // Same as C++14 make_reverse_iterator but used in C++11 mode too.
@@ -1659,12 +1633,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
 	{ return ranges::iter_swap(__x._M_current, __y._M_current); }
 #endif // C++20
-    };
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator==(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator==(const move_iterator& __x,
 		   const move_iterator<_IteratorR>& __y)
 #if __cplusplus > 201703L && __glibcxx_concepts
 	requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; }
@@ -1672,56 +1645,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{ return __x.base() == __y.base(); }
 
 #if __cpp_lib_three_way_comparison
-  template<typename _IteratorL,
-	   three_way_comparable_with<_IteratorL> _IteratorR>
+      template<three_way_comparable_with<_Iterator> _IteratorR>
 	[[__nodiscard__]]
-    constexpr compare_three_way_result_t<_IteratorL, _IteratorR>
-    operator<=>(const move_iterator<_IteratorL>& __x,
+	friend constexpr compare_three_way_result_t<_Iterator, _IteratorR>
+	operator<=>(const move_iterator& __x,
 		    const move_iterator<_IteratorR>& __y)
 	{ return __x.base() <=> __y.base(); }
 #else
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator!=(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator!=(const move_iterator& __x,
 		   const move_iterator<_IteratorR>& __y)
 	{ return !(__x == __y); }
 #endif
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator<(const move_iterator& __x,
 		  const move_iterator<_IteratorR>& __y)
 #if __cplusplus > 201703L && __glibcxx_concepts
 	requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
 #endif
 	{ return __x.base() < __y.base(); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<=(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator<=(const move_iterator& __x,
 		   const move_iterator<_IteratorR>& __y)
 #if __cplusplus > 201703L && __glibcxx_concepts
 	requires requires { { __y.base() < __x.base() } -> convertible_to<bool>; }
 #endif
 	{ return !(__y < __x); }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator>(const move_iterator& __x,
 		  const move_iterator<_IteratorR>& __y)
 #if __cplusplus > 201703L && __glibcxx_concepts
 	requires requires { { __y.base() < __x.base() } -> convertible_to<bool>; }
 #endif
 	{ return __y < __x; }
 
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>=(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR bool
+	operator>=(const move_iterator& __x,
 		   const move_iterator<_IteratorR>& __y)
 #if __cplusplus > 201703L && __glibcxx_concepts
 	requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; }
@@ -1731,72 +1703,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Note: See __normal_iterator operators note from Gaby to understand
       // why we have these extra overloads for some move_iterator operators.
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator==(const move_iterator<_Iterator>& __x,
-	       const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator==(const move_iterator& __x, const move_iterator& __y)
       { return __x.base() == __y.base(); }
 
-#if __cpp_lib_three_way_comparison
-  template<three_way_comparable _Iterator>
+#if !__cpp_lib_three_way_comparison
       [[__nodiscard__]]
-    constexpr compare_three_way_result_t<_Iterator>
-    operator<=>(const move_iterator<_Iterator>& __x,
-		const move_iterator<_Iterator>& __y)
-    { return __x.base() <=> __y.base(); }
-#else
-  template<typename _Iterator>
-    [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator!=(const move_iterator<_Iterator>& __x,
-	       const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator!=(const move_iterator& __x, const move_iterator& __y)
       { return !(__x == __y); }
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<(const move_iterator<_Iterator>& __x,
-	      const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator<(const move_iterator& __x, const move_iterator& __y)
       { return __x.base() < __y.base(); }
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator<=(const move_iterator<_Iterator>& __x,
-	       const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator<=(const move_iterator& __x, const move_iterator& __y)
       { return !(__y < __x); }
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>(const move_iterator<_Iterator>& __x,
-	      const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator>(const move_iterator& __x, const move_iterator& __y)
       { return __y < __x; }
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR bool
-    operator>=(const move_iterator<_Iterator>& __x,
-	       const move_iterator<_Iterator>& __y)
+      friend inline _GLIBCXX17_CONSTEXPR bool
+      operator>=(const move_iterator& __x, const move_iterator& __y)
       { return !(__x < __y); }
 #endif // ! C++20
 
       // DR 685.
-  template<typename _IteratorL, typename _IteratorR>
+      template<typename _IteratorR>
 	[[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR auto
-    operator-(const move_iterator<_IteratorL>& __x,
+	friend inline _GLIBCXX17_CONSTEXPR auto
+	operator-(const move_iterator& __x,
 		  const move_iterator<_IteratorR>& __y)
 	-> decltype(__x.base() - __y.base())
 	{ return __x.base() - __y.base(); }
 
-  template<typename _Iterator>
       [[__nodiscard__]]
-    inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator>
-    operator+(typename move_iterator<_Iterator>::difference_type __n,
-	      const move_iterator<_Iterator>& __x)
+      friend inline _GLIBCXX17_CONSTEXPR move_iterator
+      operator+(difference_type __n, const move_iterator& __x)
       { return __x + __n; }
+    };
 
   template<typename _Iterator>
     [[__nodiscard__]]
diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 0d60eaba194..819d6915c22 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -994,23 +994,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 	}
 #endif // C++11
-    };
-
-  /// @relates pair @{
-
-#if __cpp_deduction_guides >= 201606
-  template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>;
-#endif
 
 #if __cpp_lib_three_way_comparison
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 3865. Sorting a range of pairs
 
       /// Two pairs are equal iff their members are equal.
-  template<typename _T1, typename _T2, typename _U1, typename _U2>
+      template<typename _U1, typename _U2>
 	[[nodiscard]]
-    constexpr bool
-    operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
+	friend constexpr bool
+	operator==(const pair& __x, const pair<_U1, _U2>& __y)
 	requires requires {
 	  { __x.first == __y.first } -> __detail::__boolean_testable;
 	  { __x.second == __y.second } -> __detail::__boolean_testable;
@@ -1024,9 +1017,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        * are equivalent (neither is less than the other) and `P.second` is
        * less than `Q.second`.
        */
-  template<typename _T1, typename _T2, typename _U1, typename _U2>
+      template<typename _U1, typename _U2>
 	[[nodiscard]]
-    constexpr common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>,
+	friend constexpr common_comparison_category_t<
+	  __detail::__synth3way_t<_T1, _U1>,
 	  __detail::__synth3way_t<_T2, _U2>>
 	operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
 	{
@@ -1036,10 +1030,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
 #else
       /// Two pairs of the same type are equal iff their members are equal.
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator==(const pair& __x, const pair& __y)
       { return __x.first == __y.first && __x.second == __y.second; }
 
       /** Defines a lexicographical order for pairs.
@@ -1049,41 +1042,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        * are equivalent (neither is less than the other) and `P.second` is less
        * than `Q.second`.
        */
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator<(const pair& __x, const pair& __y)
       { return __x.first < __y.first
 	  || (!(__y.first < __x.first) && __x.second < __y.second); }
 
       /// Uses @c operator== to find the result.
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator!=(const pair& __x, const pair& __y)
       { return !(__x == __y); }
 
       /// Uses @c operator< to find the result.
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator>(const pair& __x, const pair& __y)
       { return __y < __x; }
 
       /// Uses @c operator< to find the result.
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator<=(const pair& __x, const pair& __y)
       { return !(__y < __x); }
 
       /// Uses @c operator< to find the result.
-  template<typename _T1, typename _T2>
       _GLIBCXX_NODISCARD
-    inline _GLIBCXX_CONSTEXPR bool
-    operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
+      friend inline _GLIBCXX_CONSTEXPR bool
+      operator>=(const pair& __x, const pair& __y)
       { return !(__x < __y); }
 #endif // !(three_way_comparison && concepts)
+    };
+
+  /// @relates pair @{
+
+#if __cpp_deduction_guides >= 201606
+  template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>;
+#endif
 
 #if __cplusplus >= 201103L
   /** Swap overload for pairs. Calls std::pair::swap().
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 182ad41ed94..8845135a6ba 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -2049,17 +2049,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	_M_data_ptr(_Ptr __ptr) const
 	{ return empty() ? (const value_type*)0 : __ptr.operator->(); }
 #endif
-    };
-
-#if __cpp_deduction_guides >= 201606
-  template<typename _InputIterator, typename _ValT
-	     = typename iterator_traits<_InputIterator>::value_type,
-	   typename _Allocator = allocator<_ValT>,
-	   typename = _RequireInputIter<_InputIterator>,
-	   typename = _RequireAllocator<_Allocator>>
-    vector(_InputIterator, _InputIterator, _Allocator = _Allocator())
-      -> vector<_ValT, _Allocator>;
-#endif
 
       /**
        *  @brief  Vector equality comparison.
@@ -2071,13 +2060,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  vectors.  Vectors are considered equivalent if their sizes are equal,
        *  and if corresponding elements compare equal.
        */
-  template<typename _Tp, typename _Alloc>
       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
-    inline bool
-    operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      friend inline bool
+      operator==(const vector& __x, const vector& __y)
       { return (__x.size() == __y.size()
 		&& std::equal(__x.begin(), __x.end(), __y.begin())); }
 
+
 #if __cpp_lib_three_way_comparison
       /**
        *  @brief  Vector ordering relation.
@@ -2090,10 +2079,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  is made. This operator is used to synthesize relational operators like
        *  `<` and `>=` etc.
        */
-  template<typename _Tp, typename _Alloc>
+      template<typename _Up>
 	[[nodiscard]] _GLIBCXX20_CONSTEXPR
-    inline __detail::__synth3way_t<_Tp>
-    operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+	friend inline enable_if_t<is_same_v<_Tp, _Up> &&
+				  three_way_comparable<_Up>,
+				  __detail::__synth3way_t<_Up>>
+	operator<=>(const vector<_Up, _Alloc>& __x,
+		    const vector<_Up, _Alloc>& __y)
 	{
 	  return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
 							__y.begin(), __y.end(),
@@ -2111,36 +2103,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *
        *  See std::lexicographical_compare() for how the determination is made.
        */
-  template<typename _Tp, typename _Alloc>
-    _GLIBCXX_NODISCARD inline bool
-    operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      _GLIBCXX_NODISCARD friend inline bool
+      operator<(const vector& __x, const vector& __y)
       { return std::lexicographical_compare(__x.begin(), __x.end(),
 					    __y.begin(), __y.end()); }
 
       /// Based on operator==
-  template<typename _Tp, typename _Alloc>
-    _GLIBCXX_NODISCARD inline bool
-    operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      _GLIBCXX_NODISCARD friend inline bool
+      operator!=(const vector& __x, const vector& __y)
       { return !(__x == __y); }
 
       /// Based on operator<
-  template<typename _Tp, typename _Alloc>
-    _GLIBCXX_NODISCARD inline bool
-    operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      _GLIBCXX_NODISCARD friend inline bool
+      operator>(const vector& __x, const vector& __y)
       { return __y < __x; }
 
       /// Based on operator<
-  template<typename _Tp, typename _Alloc>
-    _GLIBCXX_NODISCARD inline bool
-    operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      _GLIBCXX_NODISCARD friend inline bool
+      operator<=(const vector& __x, const vector& __y)
       { return !(__y < __x); }
 
       /// Based on operator<
-  template<typename _Tp, typename _Alloc>
-    _GLIBCXX_NODISCARD inline bool
-    operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+      _GLIBCXX_NODISCARD friend inline bool
+      operator>=(const vector& __x, const vector& __y)
       { return !(__x < __y); }
 #endif // three-way comparison
+    };
+
+#if __cpp_deduction_guides >= 201606
+  template<typename _InputIterator, typename _ValT
+	     = typename iterator_traits<_InputIterator>::value_type,
+	   typename _Allocator = allocator<_ValT>,
+	   typename = _RequireInputIter<_InputIterator>,
+	   typename = _RequireAllocator<_Allocator>>
+    vector(_InputIterator, _InputIterator, _Allocator = _Allocator())
+      -> vector<_ValT, _Allocator>;
+#endif
 
   /// See std::vector::swap().
   template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 70cf4dba7b9..4faca95eeef 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -251,13 +251,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cpp_lib_tuple_like // >= C++23
   struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
+#endif
 
+#if __cpp_lib_three_way_comparison
   // This forward declaration is used by the operator<=> overload for
   // tuple-like types.
   template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
     constexpr _Cat
     __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq);
-#endif // C++23
+#endif
 
   /**
    * Contains the actual implementation of the @c tuple template, stored
@@ -1960,6 +1962,117 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       requires (is_swappable_v<const _Elements> && ...)
       { _Inherited::_M_swap(__in); }
 #endif // C++23
+
+    private:
+#if __cpp_lib_three_way_comparison
+      template<typename... _Ups>
+	requires (sizeof...(_Elements) == sizeof...(_Ups))
+	  && (requires (const _Elements& __t, const _Ups& __u) {
+	    { __t == __u } -> __detail::__boolean_testable;
+	  } && ...)
+	friend constexpr bool
+	operator== [[nodiscard]] (const tuple& __t,
+				  const tuple<_Ups...>& __u)
+	{
+	  return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
+	    // Fold == over the tuples until non-equal elements are found.
+	    return ((std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
+	  }(index_sequence_for<_Elements...>{});
+	}
+
+      template<typename... _Ups>
+	requires (sizeof...(_Elements) == sizeof...(_Ups))
+	  && (requires { typename __detail::__synth3way_t<_Elements, _Ups>; } && ...)
+	friend constexpr
+	common_comparison_category_t<__detail::__synth3way_t<_Elements, _Ups>...>
+	operator<=> [[nodiscard]] (const tuple& __t, const tuple<_Ups...>& __u)
+	{
+	  using _Cat
+	    = common_comparison_category_t<__detail::__synth3way_t<_Elements, _Ups>...>;
+	  return std::__tuple_cmp<_Cat>(__t, __u,
+					index_sequence_for<_Elements...>());
+	}
+#else
+      // This class performs the comparison operations on tuples
+      template<typename _Tp, typename _Up, size_t __i, size_t __size>
+	struct __tuple_compare
+	{
+	  static constexpr bool
+	  __eq(const _Tp& __t, const _Up& __u)
+	  {
+	    return bool(std::get<__i>(__t) == std::get<__i>(__u))
+	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
+	  }
+
+	  static constexpr bool
+	  __less(const _Tp& __t, const _Up& __u)
+	  {
+	    return bool(std::get<__i>(__t) < std::get<__i>(__u))
+	      || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
+		  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
+	  }
+	};
+
+      template<typename _Tp, typename _Up, size_t __size>
+	struct __tuple_compare<_Tp, _Up, __size, __size>
+	{
+	  static constexpr bool
+	  __eq(const _Tp&, const _Up&) { return true; }
+
+	  static constexpr bool
+	  __less(const _Tp&, const _Up&) { return false; }
+	};
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator==(const tuple& __t, const tuple<_UElements...>& __u)
+	{
+	  static_assert(sizeof...(_Elements) == sizeof...(_UElements),
+	    "tuple objects can only be compared if they have equal sizes.");
+	  using __compare = __tuple_compare<tuple<_Elements...>,
+					    tuple<_UElements...>,
+					    0, sizeof...(_Elements)>;
+	  return __compare::__eq(__t, __u);
+	}
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator<(const tuple& __t, const tuple<_UElements...>& __u)
+	{
+	  static_assert(sizeof...(_Elements) == sizeof...(_UElements),
+	    "tuple objects can only be compared if they have equal sizes.");
+	  using __compare = __tuple_compare<tuple<_Elements...>,
+					    tuple<_UElements...>,
+					    0, sizeof...(_Elements)>;
+	  return __compare::__less(__t, __u);
+	}
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator!=(const tuple& __t, const tuple<_UElements...>& __u)
+	{ return !(__t == __u); }
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator>(const tuple& __t, const tuple<_UElements...>& __u)
+	{ return __u < __t; }
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator<=(const tuple& __t, const tuple<_UElements...>& __u)
+	{ return !(__u < __t); }
+
+      template<typename... _UElements>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator>=(const tuple& __t, const tuple<_UElements...>& __u)
+	{ return !(__t < __u); }
+#endif // three_way_comparison
     };
 
 #if __cpp_deduction_guides >= 201606
@@ -1995,6 +2108,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Alloc>
 	_GLIBCXX20_CONSTEXPR
 	tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
+
+    private:
+#if __cpp_lib_three_way_comparison
+      friend constexpr bool
+      operator== [[nodiscard]] (const tuple&, const tuple&)
+      { return true; }
+
+      friend constexpr strong_ordering
+      operator<=> [[nodiscard]] (const tuple&, const tuple&)
+      { return strong_ordering::equal; }
+#else
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator==(const tuple&, const tuple& __u)
+      { return true; }
+
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator<(const tuple&, const tuple&)
+      { return false; }
+
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator!=(const tuple&, const tuple&)
+      { return false; }
+
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator>(const tuple&, const tuple&)
+      { return false; }
+
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator<=(const tuple&, const tuple& __u)
+      { return true; }
+
+      _GLIBCXX_NODISCARD
+      friend constexpr bool
+      operator>=(const tuple&, const tuple& __u)
+      { return true; }
+#endif // three_way_comparison
     };
 
 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
@@ -2392,6 +2546,110 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       noexcept(__and_<__is_nothrow_swappable<_T1>,
 		      __is_nothrow_swappable<_T2>>::value)
       { _Inherited::_M_swap(__in); }
+
+    private:
+#if __cpp_lib_three_way_comparison
+      template<typename _U1, typename _U2>
+	requires (const _T1& __t1, const _U1& __u1)
+	{ { __t1 == __u1 } -> __detail::__boolean_testable; }
+	&& requires (const _T2& __t2, const _U2& __u2)
+	{ { __t2 == __u2 } -> __detail::__boolean_testable; }
+	friend constexpr bool
+	operator== [[nodiscard]] (const tuple& __t,
+				  const tuple<_U1, _U2>& __u)
+	{
+	  return std::get<0>(__t) == std::get<0>(__u)
+	    && std::get<1>(__t) == std::get<1>(__u);
+	}
+
+      template<typename _U1, typename _U2>
+	requires { typename __detail::__synth3way_t<_T1, _U1>; }
+	&& requires { typename __detail::__synth3way_t<_T2, _U2>; }
+	friend constexpr
+	common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>,
+				     __detail::__synth3way_t<_T2, _U2>>
+	operator<=> [[nodiscard]] (const tuple& __t,
+				   const tuple<_U1, _U2>& __u)
+	{
+	  using _Cat
+	    = common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>,
+					   __detail::__synth3way_t<_T2, _U2>>;
+	  return std::__tuple_cmp<_Cat>(__t, __u,
+					index_sequence_for<_T1, _T2>());
+	}
+#else
+      // This class performs the comparison operations on tuples
+      template<typename _Tp, typename _Up, size_t __i, size_t __size>
+	struct __tuple_compare
+	{
+	  static constexpr bool
+	  __eq(const _Tp& __t, const _Up& __u)
+	  {
+	    return bool(std::get<__i>(__t) == std::get<__i>(__u))
+	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
+	  }
+
+	  static constexpr bool
+	  __less(const _Tp& __t, const _Up& __u)
+	  {
+	    return bool(std::get<__i>(__t) < std::get<__i>(__u))
+	      || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
+		  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
+	  }
+	};
+
+      template<typename _Tp, typename _Up, size_t __size>
+	struct __tuple_compare<_Tp, _Up, __size, __size>
+	{
+	  static constexpr bool
+	  __eq(const _Tp&, const _Up&) { return true; }
+
+	  static constexpr bool
+	  __less(const _Tp&, const _Up&) { return false; }
+	};
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator==(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{
+	  using __compare = __tuple_compare<tuple, tuple<_U1, _U2>, 0, 2>;
+	  return __compare::__eq(__t, __u);
+	}
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator<(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{
+	  using __compare = __tuple_compare<tuple, tuple<_U1, _U2>, 0, 2>;
+	  return __compare::__less(__t, __u);
+	}
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator!=(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{ return !(__t == __u); }
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator>(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{ return __u < __t; }
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator<=(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{ return !(__u < __t); }
+
+      template<typename _U1, typename _U2>
+	_GLIBCXX_NODISCARD
+	friend constexpr bool
+	operator>=(const tuple& __t, const tuple<_U1, _U2>& __u)
+	{ return !(__t < __u); }
+#endif // three_way_comparison
     };
 #endif // concepts && conditional_explicit
 
@@ -2519,21 +2777,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
 #if __cpp_lib_three_way_comparison
-  template<typename... _Tps, typename... _Ups>
-    requires (sizeof...(_Tps) == sizeof...(_Ups))
-      && (requires (const _Tps& __t, const _Ups& __u) {
-	{ __t == __u } -> __detail::__boolean_testable;
-      } && ...)
-    constexpr bool
-    operator== [[nodiscard]] (const tuple<_Tps...>& __t,
-			      const tuple<_Ups...>& __u)
-    {
-      return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
-	// Fold == over the tuples until non-equal elements are found.
-	return ((std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
-      }(index_sequence_for<_Tps...>{});
-    }
-
   template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
     [[nodiscard]]
     constexpr _Cat
@@ -2555,106 +2798,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       return __c;
     }
-
-  template<typename... _Tps, typename... _Ups>
-    requires (sizeof...(_Tps) == sizeof...(_Ups))
-      && (requires { typename __detail::__synth3way_t<_Tps, _Ups>; } && ...)
-    constexpr
-    common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
-    operator<=> [[nodiscard]] (const tuple<_Tps...>& __t,
-			       const tuple<_Ups...>& __u)
-    {
-      using _Cat
-	= common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
-      return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
-    }
-#else
-
-  // This class performs the comparison operations on tuples
-  template<typename _Tp, typename _Up, size_t __i, size_t __size>
-    struct __tuple_compare
-    {
-      static constexpr bool
-      __eq(const _Tp& __t, const _Up& __u)
-      {
-	return bool(std::get<__i>(__t) == std::get<__i>(__u))
-	  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
-      }
-
-      static constexpr bool
-      __less(const _Tp& __t, const _Up& __u)
-      {
-	return bool(std::get<__i>(__t) < std::get<__i>(__u))
-	  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
-	      && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
-      }
-    };
-
-  template<typename _Tp, typename _Up, size_t __size>
-    struct __tuple_compare<_Tp, _Up, __size, __size>
-    {
-      static constexpr bool
-      __eq(const _Tp&, const _Up&) { return true; }
-
-      static constexpr bool
-      __less(const _Tp&, const _Up&) { return false; }
-    };
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator==(const tuple<_TElements...>& __t,
-	       const tuple<_UElements...>& __u)
-    {
-      static_assert(sizeof...(_TElements) == sizeof...(_UElements),
-	  "tuple objects can only be compared if they have equal sizes.");
-      using __compare = __tuple_compare<tuple<_TElements...>,
-					tuple<_UElements...>,
-					0, sizeof...(_TElements)>;
-      return __compare::__eq(__t, __u);
-    }
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator<(const tuple<_TElements...>& __t,
-	      const tuple<_UElements...>& __u)
-    {
-      static_assert(sizeof...(_TElements) == sizeof...(_UElements),
-	  "tuple objects can only be compared if they have equal sizes.");
-      using __compare = __tuple_compare<tuple<_TElements...>,
-					tuple<_UElements...>,
-					0, sizeof...(_TElements)>;
-      return __compare::__less(__t, __u);
-    }
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator!=(const tuple<_TElements...>& __t,
-	       const tuple<_UElements...>& __u)
-    { return !(__t == __u); }
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator>(const tuple<_TElements...>& __t,
-	      const tuple<_UElements...>& __u)
-    { return __u < __t; }
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator<=(const tuple<_TElements...>& __t,
-	       const tuple<_UElements...>& __u)
-    { return !(__u < __t); }
-
-  template<typename... _TElements, typename... _UElements>
-    _GLIBCXX_NODISCARD
-    constexpr bool
-    operator>=(const tuple<_TElements...>& __t,
-	       const tuple<_UElements...>& __u)
-    { return !(__t < __u); }
 #endif // three_way_comparison
 
   // NB: DR 705.
diff --git a/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc b/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc
new file mode 100644
index 00000000000..3cd5ee4f53a
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/operators/clean_diagnostics20_neg.cc
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++20 xfail *-*-* } }
+// { dg-add-options no_pch }
+
+//#include <bits/stdc++.h>
+#include <vector>
+#include <tuple>
+
+using namespace std;
+
+struct NoOperators
+{
+};
+
+int main()
+{
+  NoOperators s1, s2;
+  bool res [[maybe_unused]] = s1 == s2; // { dg-error "no match" }
+  res = s1 < s2; // { dg-error "no match" }
+  res = s1 != s2; // { dg-error "no match" }
+  res = s1 > s2; // { dg-error "no match" }
+  res = s1 <= s2; // { dg-error "no match" }
+  res = s1 >= s2; // { dg-error "no match" }
+  auto way [[maybe_unused]] = s1 <=> s2; // { dg-error "no match" }
+}
diff --git a/libstdc++-v3/testsuite/std/operators/clean_diagnostics_neg.cc b/libstdc++-v3/testsuite/std/operators/clean_diagnostics_neg.cc
new file mode 100644
index 00000000000..57a328f1a7a
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/operators/clean_diagnostics_neg.cc
@@ -0,0 +1,25 @@
+// { dg-do compile { xfail *-*-* } }
+// { dg-add-options no_pch }
+
+//#include <bits/stdc++.h>
+#include <vector>
+#if __cplusplus >= 201103L
+#include <tuple>
+#endif
+
+using namespace std;
+
+struct NoOperators
+{
+};
+
+int main()
+{
+  NoOperators s1, s2;
+  bool res __attribute__((unused)) = s1 == s2; // { dg-error "no match" }
+  res = s1 < s2; // { dg-error "no match" }
+  res = s1 != s2; // { dg-error "no match" }
+  res = s1 > s2; // { dg-error "no match" }
+  res = s1 <= s2; // { dg-error "no match" }
+  res = s1 >= s2; // { dg-error "no match" }
+}


More information about the Libstdc++ mailing list