public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Re-implement predefined operators
@ 2024-06-05 16:56 François Dumont
  0 siblings, 0 replies; only message in thread
From: François Dumont @ 2024-06-05 16:56 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2702 bytes --]

Hi

With the recent fixes to std::vector implementation all 23_containers 
and 25_algorithms tests are passing in C++98 and C++20 modes.

libstdc++: Reimplement __gnu_cxx::__ops operators

Replace functors using iterators as input to adopt functors that are
matching the same Standard expectations as the ones imposed on functor-aware
algos. It forces to have iterators dereferenced at algo level and not in the
predefined functors anymore.

Also make sure that in algos implementation details functors are passed by
reference rather than by copy.

libstdc++-v3/ChangeLog:

         * include/bits/move.h
         (_GLIBCXX_FWDREF): Now substituted by a lvalue-reference in 
pre-c++11 mode.
         (_GLIBCXX_FWDCREF): New macro, substituted by a const lvalue 
reference in
         pre-c++11 mode.
         * include/bits/stl_tree.h: Replace _GLIBCXX_FWDREF usage by 
_GLIBCXX_FWDCREF.
         * include/std/functional: Include predefined_ops.h.
         (_Not_fn): Move to...
         * include/bits/predefined_ops.h: ...here, and expose a version
         in pre-C++14 mode.
         (__not_fn): New, use latter.
         (_Iter_less_iter, _Iter_less_val, _Val_less_iter, 
_Iter_equal_to_iter)
         (_Iter_equal_to_val, _Iter_comp_iter, _Iter_comp_val, 
_Val_comp_iter)
         (_Iter_equals_val, _Iter_equals_iter, _Iter_pred, _Iter_comp_val)
         (_Iter_comp_to_val, _Iter_comp_to_iter, _Iter_negate): Remove.
         (__iter_less_iter, __iter_less_val, __iter_comp_val, 
__val_less_iter)
         (__val_comp_iter, __iter_equal_to_iter, __iter_equal_to_val, 
__iter_comp_iter)
         (__val_comp_iter, __iter_equals_val, __iter_comp_iter, 
__pred_iter): Remove.
         (_Less, _Equal_to, _Equal_to_val, _Comp_val): New.
         (__less, __equal_to, __comp_val): New.
         * include/bits/stl_algo.h: Adapt all algos to use new 
__gnu_cxx::__ops operators.
         When possible use std::move to pass predicates between routines.
         * include/bits/stl_algobase.h: Likewise.
         * include/bits/stl_heap.h: Likewise.
         * include/std/deque: Cleanup usage of __gnu_cxx::__ops 
operators. Replace usage of
         std::ref by std::move to pass predicate to std::__remove_if.
         * include/std/string: Likewise.
         * include/std/vector: Likewise.
         * src/c++17/memory_resource.cc: Include <functional>.

I'm not proud of the _GLIBCXX_FWDCREF but I'm sure you'll find a better 
name !

Ok to commit once I've completed the test coverage ?

François

[-- Attachment #2: predefined_ops_patch.txt --]
[-- Type: text/plain, Size: 142266 bytes --]

diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index bb200c95964..24f87ae4095 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -181,10 +181,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// @} group utilities
 
 #define _GLIBCXX_FWDREF(_Tp) _Tp&&
+#define _GLIBCXX_FWDCREF(_Tp) _Tp&&
 #define _GLIBCXX_MOVE(__val) std::move(__val)
 #define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
 #else
-#define _GLIBCXX_FWDREF(_Tp) const _Tp&
+#define _GLIBCXX_FWDREF(_Tp) _Tp&
+#define _GLIBCXX_FWDCREF(_Tp) const _Tp&
 #define _GLIBCXX_MOVE(__val) (__val)
 #define _GLIBCXX_FORWARD(_Tp, __val) (__val)
 #endif
diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h
index f72d511210a..cb9017b6840 100644
--- a/libstdc++-v3/include/bits/predefined_ops.h
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -31,377 +31,523 @@
 #define _GLIBCXX_PREDEFINED_OPS_H	1
 
 #include <bits/move.h>
+#include <bits/stl_iterator_base_types.h>
+
+#if __cplusplus >= 201103L
+# include <bits/invoke.h>
+#endif
 
 namespace __gnu_cxx
 {
 namespace __ops
 {
-  struct _Iter_less_iter
+#if __cplusplus >= 201103L
+  struct _Less
   {
-    template<typename _Iterator1, typename _Iterator2>
+    template<typename _Lhs, typename _Rhs>
       _GLIBCXX14_CONSTEXPR
       bool
-      operator()(_Iterator1 __it1, _Iterator2 __it2) const
-      { return *__it1 < *__it2; }
+      operator()(_Lhs&& __lhs, _Rhs&& __rhs) const
+      noexcept( noexcept(__lhs < __rhs) )
+      { return __lhs < __rhs; }
   };
+#else
+  template<typename _Ref1, typename _Ref2>
+    struct _LessRefs
+    {
+      bool
+      operator()(_Ref1 __lhs, _Ref2 __rhs) const
+      { return __lhs < __rhs; }
 
-  _GLIBCXX14_CONSTEXPR
-  inline _Iter_less_iter
-  __iter_less_iter()
-  { return _Iter_less_iter(); }
+      bool
+      operator()(_Ref2 __lhs, _Ref1 __rhs) const
+      { return __lhs < __rhs; }
 
-  struct _Iter_less_val
-  {
-#if __cplusplus >= 201103L
-    constexpr _Iter_less_val() = default;
-#else
-    _Iter_less_val() { }
-#endif
+      bool
+      operator()(_Ref1 __lhs, _Ref1 __rhs) const
+      { return __lhs < __rhs; }
 
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Iter_less_val(_Iter_less_iter) { }
+      bool
+      operator()(_Ref2 __lhs, _Ref2 __rhs) const
+      { return __lhs < __rhs; }
+    };
 
-    template<typename _Iterator, typename _Value>
-      _GLIBCXX20_CONSTEXPR
+  template<typename _Ref>
+    struct _LessRefs<_Ref, _Ref>
+    {
       bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it < __val; }
-  };
+      operator()(_Ref __lhs, _Ref __rhs) const
+      { return __lhs < __rhs; }
+    };
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_less_val()
-  { return _Iter_less_val(); }
+  template<typename _Ite1, typename _Ite2>
+    struct _Less
+    : _LessRefs<typename std::iterator_traits<_Ite1>::reference,
+		typename std::iterator_traits<_Ite2>::reference>
+    { };
+
+  template<typename _Ite>
+    struct _LessCRef
+    : _LessRefs<typename std::iterator_traits<_Ite>::reference,
+		const typename std::iterator_traits<_Ite>::value_type&>
+    { };
+#endif
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_comp_val(_Iter_less_iter)
-  { return _Iter_less_val(); }
+#if __cplusplus >= 201103L
+  template<typename _Ite1, typename _Ite2>
+    constexpr _Less
+    __less(_Ite1, _Ite2) noexcept
+    { return _Less{}; }
+
+  constexpr _Less
+  __less() noexcept
+  { return _Less{}; }
+#else
+  template<typename _Ite1, typename _Ite2>
+    inline _Less<_Ite1, _Ite2>
+    __less(_Ite1, _Ite2)
+    { return _Less<_Ite1, _Ite2>(); }
+#endif
 
-  struct _Val_less_iter
-  {
 #if __cplusplus >= 201103L
-    constexpr _Val_less_iter() = default;
+  template<typename _Ite>
+    constexpr _Less
+    __less(_Ite) noexcept
+    { return _Less{}; }
 #else
-    _Val_less_iter() { }
+  template<typename _Ite>
+    inline _LessCRef<_Ite>
+    __less(_Ite)
+    { return _LessCRef<_Ite>(); }
 #endif
 
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Val_less_iter(_Iter_less_iter) { }
+#if __cplusplus >= 201103L
+  template<typename _Comp, typename _Ite1, typename _Ite2>
+    constexpr _Comp&&
+    __less(_Comp&& __comp, _Ite1, _Ite2) noexcept
+    { return std::forward<_Comp>(__comp); }
+#else
+  template<typename _Comp, typename _Ite1, typename _Ite2>
+    inline _Comp
+    __less(_Comp __comp, _Ite1, _Ite2)
+    { return __comp; }
+
+  template<typename _LessRef1, typename _LessRef2, typename _Ite1, typename _Ite2>
+    inline _Less<_Ite1, _Ite2>
+    __less(const _LessRefs<_LessRef1, _LessRef2>&, _Ite1, _Ite2)
+    { return _Less<_Ite1, _Ite2>(); }
+#endif
 
-    template<typename _Value, typename _Iterator>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Value& __val, _Iterator __it) const
-      { return __val < *__it; }
-  };
+#if __cplusplus < 201103L
+  template<typename _Ite, typename _Val>
+    struct _LessVal : _LessRefs<typename std::iterator_traits<_Ite>::reference,
+			      _Val&>
+    { };
+#endif
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_less_iter()
-  { return _Val_less_iter(); }
+#if __cplusplus >= 201103L
+  template<typename _Ite, typename _Val>
+    constexpr _Less
+    __less_val(_Ite, _Val&&) noexcept
+    { return _Less{}; }
+#else
+  template<typename _Ite, typename _Val>
+    inline _LessVal<_Ite, _Val>
+    __less_val(_Ite, _Val&)
+    { return _LessVal<_Ite, _Val>(); }
+#endif
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_comp_iter(_Iter_less_iter)
-  { return _Val_less_iter(); }
+#if __cplusplus >= 201103L
+  template<typename _Comp, typename _Ite, typename _Val>
+    constexpr _Comp&&
+    __less_val(_Comp&& __comp, _Ite, _Val&&) noexcept
+    { return std::forward<_Comp>(__comp); }
+#else
+  template<typename _Comp, typename _Ite, typename _Val>
+    inline _Comp
+    __less_val(_Comp __comp, _Ite, _Val&)
+    { return __comp; }
+
+  template<typename _Ref1, typename _Ref2, typename _Ite, typename _Val>
+    inline _LessVal<_Ite, _Val>
+    __less_val(const _LessRefs<_Ref1, _Ref2>&, _Ite, _Val&)
+    { return _LessVal<_Ite, _Val>(); }
+#endif
 
-  struct _Iter_equal_to_iter
+#if __cplusplus >= 201103L
+  struct _EqualTo
   {
-    template<typename _Iterator1, typename _Iterator2>
+    template<typename _Lhs, typename _Rhs>
       _GLIBCXX20_CONSTEXPR
       bool
-      operator()(_Iterator1 __it1, _Iterator2 __it2) const
-      { return *__it1 == *__it2; }
+      operator()(_Lhs&& __lhs, _Rhs&& __rhs) const
+      noexcept( noexcept(__lhs == __rhs) )
+      { return __lhs == __rhs; }
   };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_iter
-  __iter_equal_to_iter()
-  { return _Iter_equal_to_iter(); }
-
-  struct _Iter_equal_to_val
-  {
-    template<typename _Iterator, typename _Value>
-      _GLIBCXX20_CONSTEXPR
+#else
+  template<typename _Ref1, typename _Ref2>
+    struct _EqualToRefs
+    {
       bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it == __val; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_val
-  __iter_equal_to_val()
-  { return _Iter_equal_to_val(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_val
-  __iter_comp_val(_Iter_equal_to_iter)
-  { return _Iter_equal_to_val(); }
+      operator()(_Ref1 __lhs, _Ref2 __rhs) const
+      { return __lhs == __rhs; }
 
-  template<typename _Compare>
-    struct _Iter_comp_iter
-    {
-      _Compare _M_comp;
+      bool
+      operator()(_Ref2 __lhs, _Ref1 __rhs) const
+      { return __lhs == __rhs; }
 
-      explicit _GLIBCXX14_CONSTEXPR
-      _Iter_comp_iter(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
+      bool
+      operator()(_Ref1 __lhs, _Ref1 __rhs) const
+      { return __lhs == __rhs; }
 
-      template<typename _Iterator1, typename _Iterator2>
-        _GLIBCXX14_CONSTEXPR
-        bool
-        operator()(_Iterator1 __it1, _Iterator2 __it2)
-        { return bool(_M_comp(*__it1, *__it2)); }
+      bool
+      operator()(_Ref2 __lhs, _Ref2 __rhs) const
+      { return __lhs == __rhs; }
     };
 
-  template<typename _Compare>
-    _GLIBCXX14_CONSTEXPR
-    inline _Iter_comp_iter<_Compare>
-    __iter_comp_iter(_Compare __comp)
-    { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
-
-  template<typename _Compare>
-    struct _Iter_comp_val
+  template<typename _Ref>
+    struct _EqualToRefs<_Ref, _Ref>
     {
-      _Compare _M_comp;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
+      bool
+      operator()(_Ref __lhs, _Ref __rhs) const
+      { return __lhs == __rhs; }
+    };
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
-	: _M_comp(__comp._M_comp)
-      { }
+  template<typename _Ite1, typename _Ite2>
+    struct _EqualTo
+      : _EqualToRefs<typename std::iterator_traits<_Ite1>::reference,
+		     typename std::iterator_traits<_Ite2>::reference>
+    { };
+#endif
 
 #if __cplusplus >= 201103L
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
-	: _M_comp(std::move(__comp._M_comp))
-      { }
+  template<typename _Ite1, typename _Ite2>
+    constexpr _EqualTo
+    __equal_to(_Ite1, _Ite2) noexcept
+    { return _EqualTo{}; }
+
+  constexpr _EqualTo
+  __equal_to() noexcept
+  { return _EqualTo{}; }
+#else
+  template<typename _Ite1, typename _Ite2>
+    inline _EqualTo<_Ite1, _Ite2>
+    __equal_to(_Ite1, _Ite2)
+    { return _EqualTo<_Ite1, _Ite2>(); }
 #endif
 
-      template<typename _Iterator, typename _Value>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it, _Value& __val)
-	{ return bool(_M_comp(*__it, __val)); }
-    };
-
-  template<typename _Compare>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_val<_Compare>
-    __iter_comp_val(_Compare __comp)
-    { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
-
-  template<typename _Compare>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_val<_Compare>
-    __iter_comp_val(_Iter_comp_iter<_Compare> __comp)
-    { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
-
-  template<typename _Compare>
-    struct _Val_comp_iter
-    {
-      _Compare _M_comp;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Val_comp_iter(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp)
-	: _M_comp(__comp._M_comp)
-      { }
-
 #if __cplusplus >= 201103L
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp)
-	: _M_comp(std::move(__comp._M_comp))
-      { }
+  template<typename _Ite>
+    constexpr _EqualTo
+    __equal_to(_Ite) noexcept
+    { return _EqualTo{}; }
+#else
+  template<typename _Ite>
+    inline _EqualTo<_Ite, _Ite>
+    __equal_to(_Ite)
+    { return _EqualTo<_Ite, _Ite>(); }
 #endif
 
-      template<typename _Value, typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Value& __val, _Iterator __it)
-	{ return bool(_M_comp(__val, *__it)); }
-    };
-
-  template<typename _Compare>
-    _GLIBCXX20_CONSTEXPR
-    inline _Val_comp_iter<_Compare>
-    __val_comp_iter(_Compare __comp)
-    { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+#if __cplusplus < 201103L
+  template<typename _Ite, typename _Val>
+    struct _EqualToVal
+      : _EqualToRefs<typename std::iterator_traits<_Ite>::reference, _Val&>
+    { };
+#endif
 
-  template<typename _Compare>
-    _GLIBCXX20_CONSTEXPR
-    inline _Val_comp_iter<_Compare>
-    __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
-    { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+#if __cplusplus >= 201103L
+  template<typename _Comp, typename _Ite, typename _Val>
+    constexpr _Comp&&
+    __equal_to_val(_Comp&& __comp, _Ite, _Val&&) noexcept
+    { return std::forward<_Comp>(__comp); }
+#else
+  template<typename _Comp, typename _Ite, typename _Val>
+    inline _Comp
+    __equal_to_val(_Comp __comp, _Ite, _Val&)
+    { return __comp; }
+
+  template<typename _Ref1, typename _Ref2, typename _Ite, typename _Val>
+    inline _EqualToVal<_Ite, _Val>
+    __equal_to_val(const _EqualToRefs<_Ref1, _Ref2>&, _Ite, _Val&)
+    { return _EqualToVal<_Ite, _Val>(); }
+#endif
 
-  template<typename _Value>
-    struct _Iter_equals_val
+#if __cplusplus >= 201103L
+  template<typename _Val>
+    struct _EqualVal
     {
-      _Value& _M_value;
+    private:
+      _Val _M_val;
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_val(_Value& __value)
-	: _M_value(__value)
-      { }
+    public:
+      constexpr
+      _EqualVal(_Val __val)
+      : _M_val(__val) { }
 
-      template<typename _Iterator>
+      template<typename _Lhs>
 	_GLIBCXX20_CONSTEXPR
 	bool
-	operator()(_Iterator __it)
-	{ return *__it == _M_value; }
+	operator()(_Lhs&& __lhs) const
+	noexcept( noexcept(__lhs == _M_val) )
+	{ return __lhs == _M_val; }
     };
-
-  template<typename _Value>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_equals_val<_Value>
-    __iter_equals_val(_Value& __val)
-    { return _Iter_equals_val<_Value>(__val); }
-
-  template<typename _Iterator1>
-    struct _Iter_equals_iter
+#else
+  template<typename _Ref, typename _Val>
+    struct _EqualValRef
     {
-      _Iterator1 _M_it1;
+    private:
+      _Val _M_val;
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_iter(_Iterator1 __it1)
-	: _M_it1(__it1)
+    public:
+      _EqualValRef(_Val __val)
+      : _M_val(__val)
       { }
 
-      template<typename _Iterator2>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator2 __it2)
-	{ return *__it2 == *_M_it1; }
+      bool
+      operator()(_Ref __lhs) const
+      { return __lhs == _M_val; }
     };
 
-  template<typename _Iterator>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_equals_iter<_Iterator>
-    __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it)
-    { return _Iter_equals_iter<_Iterator>(__it); }
-
-  template<typename _Predicate>
-    struct _Iter_pred
+  template<typename _Ite, typename _Val>
+    struct _EqualVal
+    : _EqualValRef<typename std::iterator_traits<_Ite>::reference, _Val>
     {
-      _Predicate _M_pred;
+      typedef
+      _EqualValRef<typename std::iterator_traits<_Ite>::reference, _Val> _Base;
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_pred(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
+      _EqualVal(_Val __val)
+      : _Base(__val)
       { }
-
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_pred(*__it)); }
     };
+#endif
 
-  template<typename _Predicate>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_pred<_Predicate>
-    __pred_iter(_Predicate __pred)
-    { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); }
+#if __cplusplus >= 201103L
+  template<typename _Ite, typename _Val>
+    constexpr _EqualVal<const _Val&>
+    __equal_val(_Ite, const _Val& __val) noexcept
+    {return _EqualVal<const _Val&>(__val);}
+
+  template<typename _Val>
+    constexpr _EqualVal<const _Val&>
+    __equal_val(const _Val& __val) noexcept
+    {return _EqualVal<const _Val&>(__val);}
+#else
+  template<typename _Ite, typename _Val>
+    inline _EqualVal<_Ite, const _Val&>
+    __equal_val(_Ite, const _Val& __val)
+    { return _EqualVal<_Ite, const _Val&>(__val); }
+#endif
 
-  template<typename _Compare, typename _Value>
-    struct _Iter_comp_to_val
+#if __cplusplus >= 201103L
+  template<typename _BinaryPred, typename _Val>
+    struct _CompVal
     {
-      _Compare _M_comp;
-      _Value& _M_value;
-
-      _GLIBCXX20_CONSTEXPR
-      _Iter_comp_to_val(_Compare __comp, _Value& __value)
-	: _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value)
+      template<typename _BPred>
+	constexpr
+	_CompVal(_BPred&& __pred, _Val __val)
+	: _M_binary_pred(std::forward<_BPred>(__pred))
+	, _M_val(__val)
+	{ }
+
+      _CompVal(const _CompVal&) = default;
+      _CompVal(_CompVal&&) = default;
+      ~_CompVal() = default;
+
+      // Macro to define operator() with given cv-qualifiers ref-qualifiers,
+      // forwarding _M_binary_pred and the function arguments with the same
+      // qualifiers, and deducing the return type and exception-specification.
+# define _GLIBCXX_BINARY_PRED_CALL_OP( _QUALS )				\
+      template<typename _Arg,						\
+	       typename = std::__enable_if_t<std::__is_invocable<	\
+		 _BinaryPred _QUALS, _Arg, _Val>::value>> 	\
+	_GLIBCXX20_CONSTEXPR						\
+	bool								\
+	operator()(_Arg&& __arg) _QUALS					\
+	noexcept(std::__is_nothrow_invocable<				\
+		 _BinaryPred _QUALS, _Arg, _Val>::value)		\
+	{								\
+	  return std::__invoke(						\
+		   std::forward< _BinaryPred _QUALS >(_M_binary_pred),	\
+		   std::forward<_Arg>(__arg), _M_val);			\
+	}								\
+									\
+      template<typename _Arg,						\
+	       typename = std::__enable_if_t<!std::__is_invocable<	\
+		 _BinaryPred _QUALS, _Arg, _Val>::value>>	\
+	void operator()(_Arg&&) _QUALS = delete;
+
+      _GLIBCXX_BINARY_PRED_CALL_OP( & )
+      _GLIBCXX_BINARY_PRED_CALL_OP( const & )
+      _GLIBCXX_BINARY_PRED_CALL_OP( && )
+      _GLIBCXX_BINARY_PRED_CALL_OP( const && )
+# undef _GLIBCXX_BINARY_PRED_CALL_OP
+#else
+  template<typename _BinaryPred, typename _Ite, typename _Val>
+    struct _CompVal
+    {
+      _CompVal(_BinaryPred __pred, _Val __val)
+      : _M_binary_pred(__pred), _M_val(__val)
       { }
 
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_comp(*__it, _M_value)); }
+      bool
+      operator()(typename std::iterator_traits<_Ite>::reference __lhs)
+      { return bool(_M_binary_pred(__lhs, _M_val)); }
+#endif
+
+    private:
+      _BinaryPred _M_binary_pred;
+      _Val	  _M_val;
     };
 
-  template<typename _Compare, typename _Value>
-    _Iter_comp_to_val<_Compare, _Value>
-    _GLIBCXX20_CONSTEXPR
-    __iter_comp_val(_Compare __comp, _Value &__val)
+#if __cplusplus >= 201103L
+  template<typename _BPred, typename _Ite, typename _Val>
+    _GLIBCXX20_CONSTEXPR inline
+    _CompVal<std::__decay_t<_BPred>, const _Val&>
+    __comp_val(_BPred&& __pred, _Ite, const _Val& __val)
+    noexcept(std::is_nothrow_constructible<std::__decay_t<_BPred>,
+	     _BPred&&>::value)
     {
-      return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val);
+      return
+	_CompVal<std::__decay_t<_BPred>, const _Val&>
+	(std::forward<_BPred>(__pred), __val);
     }
+#else
+  template<typename _BPred, typename _Ite, typename _Val>
+    inline _CompVal<_BPred, _Ite, const _Val&>
+    __comp_val(_BPred __pred, _Ite, const _Val& __val)
+    { return _CompVal<_BPred, _Ite, const _Val&>(__pred, __val); }
+#endif
 
-  template<typename _Compare, typename _Iterator1>
-    struct _Iter_comp_to_iter
+#if __cplusplus >= 201103L
+  template<typename _BPred, typename _InIte, typename _Ite>
+    _GLIBCXX20_CONSTEXPR inline
+    _CompVal<std::__decay_t<_BPred>,
+	     typename std::iterator_traits<_Ite>::reference>
+    __equal_ite(_BPred&& __pred, _InIte, _Ite  __ite)
+    noexcept(std::is_nothrow_constructible<std::__decay_t<_BPred>,
+	     _BPred&&>::value)
     {
-      _Compare _M_comp;
-      _Iterator1 _M_it1;
-
-      _GLIBCXX20_CONSTEXPR
-      _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
-	: _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1)
-      { }
-
-      template<typename _Iterator2>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator2 __it2)
-	{ return bool(_M_comp(*__it2, *_M_it1)); }
-    };
+      return
+	_CompVal<std::__decay_t<_BPred>,
+		 typename std::iterator_traits<_Ite>::reference>
+	(std::forward<_BPred>(__pred), *__ite);
+    }
 
-  template<typename _Compare, typename _Iterator>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_to_iter<_Compare, _Iterator>
-    __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
+  template<typename _InIte, typename _Ite>
+    _GLIBCXX20_CONSTEXPR inline
+    _EqualVal<typename std::iterator_traits<_Ite>::reference>
+    __equal_ite(_EqualTo, _InIte, _Ite __ite)
     {
-      return _Iter_comp_to_iter<_Compare, _Iterator>(
-	  _GLIBCXX_MOVE(__comp._M_comp), __it);
+      return
+	_EqualVal<typename std::iterator_traits<_Ite>::reference>(*__ite);
+    }
+#else
+  template<typename _BPred, typename _InIte, typename _Ite>
+    inline
+      _CompVal<_BPred, _InIte, typename std::iterator_traits<_Ite>::reference>
+    __equal_ite(_BPred __pred, _InIte, _Ite __ite)
+    {
+      return
+	_CompVal<_BPred, _InIte, typename std::iterator_traits<_Ite>::reference>
+	(__pred, *__ite);
     }
 
-  template<typename _Predicate>
-    struct _Iter_negate
+  template<typename _Ref1, typename _Ref2, typename _InIte, typename _Ite>
+    inline
+      _EqualVal<_InIte, typename std::iterator_traits<_Ite>::reference>
+    __equal_ite(const _EqualToRefs<_Ref1, _Ref2>&, _InIte, _Ite __ite)
     {
-      _Predicate _M_pred;
+      return
+	_EqualVal<_InIte, typename std::iterator_traits<_Ite>::reference>
+	(*__ite);
+    }
+#endif
+} // namespace __ops
+} // namespace __gnu_cxx
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_negate(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
-      { }
 
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return !bool(_M_pred(*__it)); }
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if __cplusplus >= 201103L
+  /// Generalized negator.
+  template<typename _Fn>
+    class _Not_fn
+    {
+      template<typename _Fn2, typename... _Args>
+	using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type;
+
+      template<typename _Tp>
+	static decltype(!std::declval<_Tp>())
+	_S_not() noexcept(noexcept(!std::declval<_Tp>()));
+
+    public:
+      template<typename _Fn2>
+	constexpr
+	_Not_fn(_Fn2&& __fn, int)
+	: _M_fn(std::forward<_Fn2>(__fn)) { }
+
+      _Not_fn(const _Not_fn& __fn) = default;
+      _Not_fn(_Not_fn&& __fn) = default;
+      ~_Not_fn() = default;
+
+      // Macro to define operator() with given cv-qualifiers ref-qualifiers,
+      // forwarding _M_fn and the function arguments with the same qualifiers,
+      // and deducing the return type and exception-specification.
+# define _GLIBCXX_NOT_FN_CALL_OP( _QUALS )				\
+      template<typename... _Args,					\
+	       typename = __enable_if_t<__is_invocable<_Fn _QUALS, _Args...>::value>> \
+	_GLIBCXX20_CONSTEXPR						\
+	decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())		\
+	operator()(_Args&&... __args) _QUALS				\
+	noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value	\
+	    && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()))	\
+	{								\
+	  return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn),	\
+				std::forward<_Args>(__args)...);	\
+	}								\
+									\
+      template<typename... _Args,					\
+	       typename = __enable_if_t<!__is_invocable<_Fn _QUALS, _Args...>::value>> \
+	void operator()(_Args&&... __args) _QUALS = delete;
+
+      _GLIBCXX_NOT_FN_CALL_OP( & )
+      _GLIBCXX_NOT_FN_CALL_OP( const & )
+      _GLIBCXX_NOT_FN_CALL_OP( && )
+      _GLIBCXX_NOT_FN_CALL_OP( const && )
+# undef _GLIBCXX_NOT_FN_CALL_OP
+#else
+  /// Generalized negator.
+  template<typename _Fn, typename _Ite>
+    class _Not_fn
+    {
+    public:
+      _Not_fn(_Fn __fn)
+      : _M_fn(__fn) { }
+
+      bool
+      operator()(typename std::iterator_traits<_Ite>::reference __arg)
+      { return !bool(_M_fn(__arg)); }
+#endif
+    private:
+      _Fn _M_fn;
     };
 
-  template<typename _Predicate>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_negate<_Predicate>
-    __negate(_Iter_pred<_Predicate> __pred)
-    { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); }
+  template<typename _Fn, typename _Ite>
+    inline _GLIBCXX20_CONSTEXPR
+#if __cplusplus >= 201103L
+    _Not_fn<std::__decay_t<_Fn>>
+    __not_fn(_Fn&& __fn, _Ite)
+    noexcept(std::is_nothrow_constructible<std::__decay_t<_Fn>, _Fn&&>::value)
+    { return _Not_fn<std::__decay_t<_Fn>>{std::forward<_Fn>(__fn), 0}; }
+#else
+    _Not_fn<_Fn, _Ite>
+    __not_fn(_Fn __fn, _Ite)
+    { return _Not_fn<_Fn, _Ite>(__fn); }
+#endif
 
-} // namespace __ops
-} // namespace __gnu_cxx
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
 
 #endif
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 1a996aa61da..0de73e28da5 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -82,21 +82,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Iterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     void
-    __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
-			   _Iterator __c, _Compare __comp)
+    __move_median_to_first(_Iterator __result, _Iterator __a, _Iterator __b,
+			   _Iterator __c, _GLIBCXX_FWDREF(_Compare) __comp)
     {
-      if (__comp(__a, __b))
+      if (__comp(*__a, *__b))
 	{
-	  if (__comp(__b, __c))
+	  if (__comp(*__b, *__c))
 	    std::iter_swap(__result, __b);
-	  else if (__comp(__a, __c))
+	  else if (__comp(*__a, *__c))
 	    std::iter_swap(__result, __c);
 	  else
 	    std::iter_swap(__result, __a);
 	}
-      else if (__comp(__a, __c))
+      else if (__comp(*__a, *__c))
 	std::iter_swap(__result, __a);
-      else if (__comp(__b, __c))
+      else if (__comp(*__b, *__c))
 	std::iter_swap(__result, __c);
       else
 	std::iter_swap(__result, __b);
@@ -107,10 +107,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     inline _InputIterator
     __find_if_not(_InputIterator __first, _InputIterator __last,
-		  _Predicate __pred)
+		  _GLIBCXX_FWDREF(_Predicate) __pred)
     {
-      return std::__find_if(__first, __last,
-			    __gnu_cxx::__ops::__negate(__pred),
+      __decltype(std::__not_fn(_GLIBCXX_FORWARD(_Predicate, __pred), __first))
+	__prd = std::__not_fn(_GLIBCXX_FORWARD(_Predicate, __pred), __first);
+      return std::__find_if(__first, __last, _GLIBCXX_MOVE(__prd),
 			    std::__iterator_category(__first));
     }
 
@@ -120,10 +121,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _InputIterator, typename _Predicate, typename _Distance>
     _GLIBCXX20_CONSTEXPR
     _InputIterator
-    __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
+    __find_if_not_n(_InputIterator __first, _Distance& __len,
+		    _GLIBCXX_FWDREF(_Predicate) __pred)
     {
       for (; __len; --__len,  (void) ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  break;
       return __first;
     }
@@ -150,7 +152,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __search_n_aux(_ForwardIterator __first, _ForwardIterator __last,
-		   _Integer __count, _UnaryPredicate __unary_pred,
+		   _Integer __count,
+		   _GLIBCXX_FWDREF(_UnaryPredicate) __unary_pred,
 		   std::forward_iterator_tag)
     {
       __first = std::__find_if(__first, __last, __unary_pred);
@@ -160,7 +163,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    __n = __count;
 	  _ForwardIterator __i = __first;
 	  ++__i;
-	  while (__i != __last && __n != 1 && __unary_pred(__i))
+	  while (__i != __last && __n != 1 && __unary_pred(*__i))
 	    {
 	      ++__i;
 	      --__n;
@@ -183,7 +186,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _RandomAccessIter
     __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last,
-		   _Integer __count, _UnaryPredicate __unary_pred,
+		   _Integer __count,
+		   _GLIBCXX_FWDREF(_UnaryPredicate) __unary_pred,
 		   std::random_access_iterator_tag)
     {
       typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
@@ -199,7 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  // __first here is always pointing to one past the last element of
 	  // next possible match.
 	  _RandomAccessIter __backTrack = __first; 
-	  while (__unary_pred(--__backTrack))
+	  while (__unary_pred(*(--__backTrack)))
 	    {
 	      if (--__remainder == 0)
 		return (__first - __count); // Success
@@ -215,16 +219,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _ForwardIterator
     __search_n(_ForwardIterator __first, _ForwardIterator __last,
 	       _Integer __count,
-	       _UnaryPredicate __unary_pred)
+	       _GLIBCXX_FWDREF(_UnaryPredicate) __unary_pred)
     {
       if (__count <= 0)
 	return __first;
 
       if (__count == 1)
-	return std::__find_if(__first, __last, __unary_pred);
+	return std::__find_if(__first, __last,
+			      _GLIBCXX_FORWARD(_UnaryPredicate, __unary_pred));
 
-      return std::__search_n_aux(__first, __last, __count, __unary_pred,
-				 std::__iterator_category(__first));
+      return std::__search_n_aux
+	(__first, __last, __count,
+	 _GLIBCXX_FORWARD(_UnaryPredicate, __unary_pred),
+	 std::__iterator_category(__first));
     }
 
   // find_end for forward iterators.
@@ -235,7 +242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
 	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
 	       forward_iterator_tag, forward_iterator_tag,
-	       _BinaryPredicate __comp)
+	       _GLIBCXX_FWDREF(_BinaryPredicate) __comp)
     {
       if (__first2 == __last2)
 	return __last1;
@@ -266,7 +273,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       _BidirectionalIterator2 __first2,
 	       _BidirectionalIterator2 __last2,
 	       bidirectional_iterator_tag, bidirectional_iterator_tag,
-	       _BinaryPredicate __comp)
+	       _GLIBCXX_FWDREF(_BinaryPredicate) __comp)
     {
       // concept requirements
       __glibcxx_function_requires(_BidirectionalIteratorConcept<
@@ -279,9 +286,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _RevIterator1 __rlast1(__first1);
       _RevIterator2 __rlast2(__first2);
-      _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1,
-					      _RevIterator2(__last2), __rlast2,
-					      __comp);
+      _RevIterator1 __rresult = std::__search
+	(_RevIterator1(__last1), __rlast1, _RevIterator2(__last2), __rlast2,
+	 _GLIBCXX_FORWARD(_BinaryPredicate, __comp));
 
       if (__rresult == __rlast1)
 	return __last1;
@@ -334,10 +341,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      return std::__find_end(__first1, __last1, __first2, __last2,
-			     std::__iterator_category(__first1),
-			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+      __decltype(__gnu_cxx::__ops::__equal_to(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first1, __first2);
+      return std::__find_end
+	(__first1, __last1, __first2, __last2,
+	 std::__iterator_category(__first1), std::__iterator_category(__first2),
+	 __comp);
     }
 
   /**
@@ -385,10 +394,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      return std::__find_end(__first1, __last1, __first2, __last2,
-			     std::__iterator_category(__first1),
-			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return std::__find_end
+	(__first1, __last1, __first2, __last2,
+	 std::__iterator_category(__first1), std::__iterator_category(__first2),
+	 _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -408,7 +417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     inline bool
     all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return __last == std::find_if_not(__first, __last, __pred); }
+    { return __last == std::find_if_not(__first, __last, std::move(__pred)); }
 
   /**
    *  @brief  Checks that a predicate is false for all the elements
@@ -426,7 +435,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     inline bool
     none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); }
+    {
+      return
+	__last == _GLIBCXX_STD_A::find_if(__first, __last, std::move(__pred));
+    }
 
   /**
    *  @brief  Checks that a predicate is true for at least one element
@@ -445,7 +457,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
     inline bool
     any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
-    { return !std::none_of(__first, __last, __pred); }
+    { return !std::none_of(__first, __last, std::move(__pred)); }
 
   /**
    *  @brief  Find the first element in a sequence for which a
@@ -468,8 +480,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
 	      typename iterator_traits<_InputIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
-      return std::__find_if_not(__first, __last,
-				__gnu_cxx::__ops::__pred_iter(__pred));
+      return std::__find_if_not(__first, __last, std::move(__pred));
     }
 
   /**
@@ -492,7 +503,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__first == __last)
 	return true;
       ++__first;
-      return std::none_of(__first, __last, __pred);
+      return std::none_of(__first, __last, std::move(__pred));
     }
 
   /**
@@ -539,17 +550,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       return __first;
     }
-#endif
+#endif // C++11
 
   template<typename _InputIterator, typename _OutputIterator,
 	   typename _Predicate>
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
     __remove_copy_if(_InputIterator __first, _InputIterator __last,
-		     _OutputIterator __result, _Predicate __pred)
+		     _OutputIterator __result,
+		     _GLIBCXX_FWDREF(_Predicate) __pred)
     {
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = *__first;
 	    ++__result;
@@ -585,8 +597,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    typename iterator_traits<_InputIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__remove_copy_if(__first, __last, __result,
-	__gnu_cxx::__ops::__iter_equals_val(__value));
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __value)) __pred =
+	__gnu_cxx::__ops::__equal_val(__first, __value);
+      return std::__remove_copy_if(__first, __last, __result, __pred);
     }
 
   /**
@@ -620,7 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__remove_copy_if(__first, __last, __result,
-				   __gnu_cxx::__ops::__pred_iter(__pred));
+				   _GLIBCXX_MOVE(__pred));
     }
 
 #if __cplusplus >= 201103L
@@ -795,8 +808,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__remove_if(__first, __last,
-		__gnu_cxx::__ops::__iter_equals_val(__value));
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __value)) __comp =
+	__gnu_cxx::__ops::__equal_val(__first, __value);
+      return std::__remove_if(__first, __last, __comp);
     }
 
   /**
@@ -829,22 +843,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__remove_if(__first, __last,
-			      __gnu_cxx::__ops::__pred_iter(__pred));
+      return std::__remove_if(__first, __last, _GLIBCXX_MOVE(__pred));
     }
 
   template<typename _ForwardIterator, typename _BinaryPredicate>
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
-		    _BinaryPredicate __binary_pred)
+		    _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred)
     {
       if (__first == __last)
 	return __last;
       _ForwardIterator __next = __first;
       while (++__next != __last)
 	{
-	  if (__binary_pred(__first, __next))
+	  if (__binary_pred(*__first, *__next))
 	    return __first;
 	  __first = __next;
 	}
@@ -855,7 +868,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __unique(_ForwardIterator __first, _ForwardIterator __last,
-	     _BinaryPredicate __binary_pred)
+	     _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred)
     {
       // Skip the beginning, if already unique.
       __first = std::__adjacent_find(__first, __last, __binary_pred);
@@ -866,7 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _ForwardIterator __dest = __first;
       ++__first;
       while (++__first != __last)
-	if (!__binary_pred(__dest, __first))
+	if (!__binary_pred(*__dest, *__first))
 	  *++__dest = _GLIBCXX_MOVE(*__first);
       return ++__dest;
     }
@@ -897,8 +910,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		     typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__unique(__first, __last,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+      __decltype(__gnu_cxx::__ops::__equal_to(__first)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first);
+      return std::__unique(__first, __last, __comp);
     }
 
   /**
@@ -930,8 +944,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__unique(__first, __last,
-			   __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+      return std::__unique(__first, __last, _GLIBCXX_MOVE(__binary_pred));
     }
 
   /**
@@ -945,7 +958,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
     __unique_copy(_ForwardIterator __first, _ForwardIterator __last,
-		  _OutputIterator __result, _BinaryPredicate __binary_pred,
+		  _OutputIterator __result,
+		  _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred,
 		  forward_iterator_tag, output_iterator_tag)
     {
       // concept requirements -- iterators already checked
@@ -956,7 +970,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _ForwardIterator __next = __first;
       *__result = *__first;
       while (++__next != __last)
-	if (!__binary_pred(__first, __next))
+	if (!__binary_pred(*__first, *__next))
 	  {
 	    __first = __next;
 	    *++__result = *__first;
@@ -975,7 +989,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _OutputIterator
     __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _OutputIterator __result, _BinaryPredicate __binary_pred,
+		  _OutputIterator __result,
+		  _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred,
 		  input_iterator_tag, output_iterator_tag)
     {
       // concept requirements -- iterators already checked
@@ -984,12 +999,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  typename iterator_traits<_InputIterator>::value_type>)
 
       typename iterator_traits<_InputIterator>::value_type __value = *__first;
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
-	__rebound_pred
-	= __gnu_cxx::__ops::__iter_comp_val(__binary_pred);
       *__result = __value;
+      __decltype(__gnu_cxx::__ops::__equal_to_val
+		 (_GLIBCXX_FORWARD(_BinaryPredicate, __binary_pred),
+		  __first, __value)) __bnry_pred =
+	__gnu_cxx::__ops::__equal_to_val
+	(_GLIBCXX_FORWARD(_BinaryPredicate, __binary_pred), __first, __value);
       while (++__first != __last)
-	if (!__rebound_pred(__first, __value))
+	if (!__bnry_pred(*__first, __value))
 	  {
 	    __value = *__first;
 	    *++__result = __value;
@@ -1008,7 +1025,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __unique_copy(_InputIterator __first, _InputIterator __last,
-		  _ForwardIterator __result, _BinaryPredicate __binary_pred,
+		  _ForwardIterator __result,
+		  _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred,
 		  input_iterator_tag, forward_iterator_tag)
     {
       // concept requirements -- iterators already checked
@@ -1017,7 +1035,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  typename iterator_traits<_InputIterator>::value_type>)
       *__result = *__first;
       while (++__first != __last)
-	if (!__binary_pred(__result, __first))
+	if (!__binary_pred(*__result, *__first))
 	  *++__result = *__first;
       return ++__result;
     }
@@ -1402,7 +1420,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __partition(_ForwardIterator __first, _ForwardIterator __last,
-		_Predicate __pred, forward_iterator_tag)
+		_GLIBCXX_FWDREF(_Predicate) __pred, forward_iterator_tag)
     {
       if (__first == __last)
 	return __first;
@@ -1428,7 +1446,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     _BidirectionalIterator
     __partition(_BidirectionalIterator __first, _BidirectionalIterator __last,
-		_Predicate __pred, bidirectional_iterator_tag)
+		_GLIBCXX_FWDREF(_Predicate) __pred, bidirectional_iterator_tag)
     {
       while (true)
 	{
@@ -1466,9 +1484,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _ForwardIterator
     __stable_partition_adaptive(_ForwardIterator __first,
 				_ForwardIterator __last,
-				_Predicate __pred, _Distance __len,
-				_Pointer __buffer,
-				_Distance __buffer_size)
+				_GLIBCXX_FWDREF(_Predicate) __pred,
+				_Distance __len,
+				_Pointer __buffer, _Distance __buffer_size)
     {
       if (__len == 1)
 	return __first;
@@ -1485,7 +1503,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  ++__result2;
 	  ++__first;
 	  for (; __first != __last; ++__first)
-	    if (__pred(__first))
+	    if (__pred(*__first))
 	      {
 		*__result1 = _GLIBCXX_MOVE(*__first);
 		++__result1;
@@ -1514,10 +1532,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	std::__find_if_not_n(__middle, __right_len, __pred);
 
       if (__right_len)
-	__right_split =
-	  std::__stable_partition_adaptive(__right_split, __last, __pred,
-					   __right_len,
-					   __buffer, __buffer_size);
+	__right_split = std::__stable_partition_adaptive
+	  (__right_split, __last, _GLIBCXX_FORWARD(_Predicate, __pred),
+	   __right_len, __buffer, __buffer_size);
 
       return std::rotate(__left_split, __middle, __right_split);
     }
@@ -1525,7 +1542,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
   template<typename _ForwardIterator, typename _Predicate>
     _ForwardIterator
     __stable_partition(_ForwardIterator __first, _ForwardIterator __last,
-		       _Predicate __pred)
+		       _GLIBCXX_FWDREF(_Predicate) __pred)
     {
       __first = std::__find_if_not(__first, __last, __pred);
 
@@ -1540,10 +1557,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _Temporary_buffer<_ForwardIterator, _ValueType>
 	__buf(__first, std::distance(__first, __last));
       return
-	std::__stable_partition_adaptive(__first, __last, __pred,
-					 _DistanceType(__buf.requested_size()),
-					 __buf.begin(),
-					 _DistanceType(__buf.size()));
+	std::__stable_partition_adaptive
+	(__first, __last, _GLIBCXX_FORWARD(_Predicate, __pred),
+	 _DistanceType(__buf.requested_size()),
+	 __buf.begin(), _DistanceType(__buf.size()));
     }
 
   /**
@@ -1575,8 +1592,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	    typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__stable_partition(__first, __last,
-				     __gnu_cxx::__ops::__pred_iter(__pred));
+      return std::__stable_partition(__first, __last, _GLIBCXX_MOVE(__pred));
     }
 #endif // HOSTED
 
@@ -1588,11 +1604,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __heap_select(_RandomAccessIterator __first,
 		  _RandomAccessIterator __middle,
-		  _RandomAccessIterator __last, _Compare __comp)
+		  _RandomAccessIterator __last,
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       std::__make_heap(__first, __middle, __comp);
       for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
-	if (__comp(__i, __first))
+	if (__comp(*__i, *__first))
 	  std::__pop_heap(__first, __middle, __i, __comp);
     }
 
@@ -1605,7 +1622,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __partial_sort_copy(_InputIterator __first, _InputIterator __last,
 			_RandomAccessIterator __result_first,
 			_RandomAccessIterator __result_last,
-			_Compare __comp)
+			_GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_InputIterator>::value_type
 	_InputValueType;
@@ -1625,14 +1642,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       std::__make_heap(__result_first, __result_real_last, __comp);
       while (__first != __last)
 	{
-	  if (__comp(__first, __result_first))
+	  if (__comp(*__first, *__result_first))
 	    std::__adjust_heap(__result_first, _DistanceType(0),
 			       _DistanceType(__result_real_last
 					     - __result_first),
 			       _InputValueType(*__first), __comp);
 	  ++__first;
 	}
-      std::__sort_heap(__result_first, __result_real_last, __comp);
+      std::__sort_heap(__result_first, __result_real_last,
+		       _GLIBCXX_FORWARD(_Compare, __comp));
       return __result_real_last;
     }
 
@@ -1681,9 +1699,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
       __glibcxx_requires_valid_range(__result_first, __result_last);
 
-      return std::__partial_sort_copy(__first, __last,
-				      __result_first, __result_last,
-				      __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first, __result_first)) __comp =
+	__gnu_cxx::__ops::__less(__first, __result_first);
+      return std::__partial_sort_copy
+	(__first, __last, __result_first, __result_last, __comp);
     }
 
   /**
@@ -1738,23 +1757,21 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       return std::__partial_sort_copy(__first, __last,
 				      __result_first, __result_last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				      _GLIBCXX_MOVE(__comp));
     }
 
   /// @cond undocumented
 
   /// This is a helper function for the sort routine.
-  template<typename _RandomAccessIterator, typename _Compare>
+  template<typename _RandomAccessIterator, typename _Val, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     void
-    __unguarded_linear_insert(_RandomAccessIterator __last,
-			      _Compare __comp)
+    __unguarded_linear_insert(_RandomAccessIterator __last, _Val __val,
+			      _GLIBCXX_FWDREF(_Compare) __comp)
     {
-      typename iterator_traits<_RandomAccessIterator>::value_type
-	__val = _GLIBCXX_MOVE(*__last);
       _RandomAccessIterator __next = __last;
       --__next;
-      while (__comp(__val, __next))
+      while (__comp(__val, *__next))
 	{
 	  *__last = _GLIBCXX_MOVE(*__next);
 	  __last = __next;
@@ -1768,13 +1785,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     void
     __insertion_sort(_RandomAccessIterator __first,
-		     _RandomAccessIterator __last, _Compare __comp)
+		     _RandomAccessIterator __last,
+		     _GLIBCXX_FWDREF(_Compare) __comp)
     {
-      if (__first == __last) return;
+      if (__first == __last)
+	return;
 
       for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
 	{
-	  if (__comp(__i, __first))
+	  if (__comp(*__i, *__first))
 	    {
 	      typename iterator_traits<_RandomAccessIterator>::value_type
 		__val = _GLIBCXX_MOVE(*__i);
@@ -1782,8 +1801,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	      *__first = _GLIBCXX_MOVE(__val);
 	    }
 	  else
-	    std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	    {
+	      typename iterator_traits<_RandomAccessIterator>::value_type
+		__val = _GLIBCXX_MOVE(*__i);
+	      std::__unguarded_linear_insert(__i, _GLIBCXX_MOVE(__val), __comp);
+	    }
 	}
     }
 
@@ -1792,11 +1814,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     inline void
     __unguarded_insertion_sort(_RandomAccessIterator __first,
-			       _RandomAccessIterator __last, _Compare __comp)
+			       _RandomAccessIterator __last,
+			       _GLIBCXX_FWDREF(_Compare) __comp)
     {
+      if (__first == __last)
+	return;
+
       for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
-	std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	{
+	  typename std::iterator_traits<_RandomAccessIterator>::value_type
+	    __val = _GLIBCXX_MOVE(*__i);
+	  std::__unguarded_linear_insert(__i, _GLIBCXX_MOVE(__val), __comp);
+	}
     }
 
   /**
@@ -1810,16 +1839,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     void
     __final_insertion_sort(_RandomAccessIterator __first,
-			   _RandomAccessIterator __last, _Compare __comp)
+			   _RandomAccessIterator __last,
+			   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__last - __first > int(_S_threshold))
 	{
 	  std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
 	  std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
-					  __comp);
+					  _GLIBCXX_FORWARD(_Compare, __comp));
 	}
       else
-	std::__insertion_sort(__first, __last, __comp);
+	std::__insertion_sort(__first, __last,
+			      _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   /// This is a helper function...
@@ -1828,14 +1859,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _RandomAccessIterator
     __unguarded_partition(_RandomAccessIterator __first,
 			  _RandomAccessIterator __last,
-			  _RandomAccessIterator __pivot, _Compare __comp)
+			  _RandomAccessIterator __pivot,
+			  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (true)
 	{
-	  while (__comp(__first, __pivot))
+	  while (__comp(*__first, *__pivot))
 	    ++__first;
 	  --__last;
-	  while (__comp(__pivot, __last))
+	  while (__comp(*__pivot, *__last))
 	    --__last;
 	  if (!(__first < __last))
 	    return __first;
@@ -1849,12 +1881,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     inline _RandomAccessIterator
     __unguarded_partition_pivot(_RandomAccessIterator __first,
-				_RandomAccessIterator __last, _Compare __comp)
+				_RandomAccessIterator __last,
+				_GLIBCXX_FWDREF(_Compare) __comp)
     {
       _RandomAccessIterator __mid = __first + (__last - __first) / 2;
-      std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
-				  __comp);
-      return std::__unguarded_partition(__first + 1, __last, __first, __comp);
+      std::__move_median_to_first
+	(__first, __first + 1, __mid, __last - 1, __comp);
+      return std::__unguarded_partition
+	(__first + 1, __last, __first, _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
@@ -1863,10 +1897,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __partial_sort(_RandomAccessIterator __first,
 		   _RandomAccessIterator __middle,
 		   _RandomAccessIterator __last,
-		   _Compare __comp)
+		   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       std::__heap_select(__first, __middle, __last, __comp);
-      std::__sort_heap(__first, __middle, __comp);
+      std::__sort_heap(__first, __middle, _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   /// This is a helper function for the sort routine.
@@ -1875,13 +1909,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __introsort_loop(_RandomAccessIterator __first,
 		     _RandomAccessIterator __last,
-		     _Size __depth_limit, _Compare __comp)
+		     _Size __depth_limit, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__last - __first > int(_S_threshold))
 	{
 	  if (__depth_limit == 0)
 	    {
-	      std::__partial_sort(__first, __last, __last, __comp);
+	      std::__partial_sort(__first, __last, __last,
+				  _GLIBCXX_FORWARD(_Compare, __comp));
 	      return;
 	    }
 	  --__depth_limit;
@@ -1898,14 +1933,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     inline void
     __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	   _Compare __comp)
+	   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first != __last)
 	{
-	  std::__introsort_loop(__first, __last,
-				std::__lg(__last - __first) * 2,
-				__comp);
-	  std::__final_insertion_sort(__first, __last, __comp);
+	  std::__introsort_loop
+	    (__first, __last, std::__lg(__last - __first) * 2, __comp);
+	  std::__final_insertion_sort
+	    (__first, __last, _GLIBCXX_FORWARD(_Compare, __comp));
 	}
     }
 
@@ -1914,13 +1949,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
 		  _RandomAccessIterator __last, _Size __depth_limit,
-		  _Compare __comp)
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__last - __first > 3)
 	{
 	  if (__depth_limit == 0)
 	    {
-	      std::__heap_select(__first, __nth + 1, __last, __comp);
+	      std::__heap_select(__first, __nth + 1, __last,
+				 _GLIBCXX_FORWARD(_Compare, __comp));
 	      // Place the nth largest element in its final position.
 	      std::iter_swap(__first, __nth);
 	      return;
@@ -1933,7 +1969,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  else
 	    __last = __cut;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort(__first, __last,
+			    _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   /// @endcond
@@ -1970,15 +2007,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_lower_pred(__first, __last,
 						__val, __comp);
 
-      return std::__lower_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_comp_val(__comp));
+      return std::__lower_bound(__first, __last, __val, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Tp, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __upper_bound(_ForwardIterator __first, _ForwardIterator __last,
-		  const _Tp& __val, _Compare __comp)
+		  const _Tp& __val, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_ForwardIterator>::difference_type
 	_DistanceType;
@@ -1990,7 +2026,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  _DistanceType __half = __len >> 1;
 	  _ForwardIterator __middle = __first;
 	  std::advance(__middle, __half);
-	  if (__comp(__val, __middle))
+	  if (__comp(__val, *__middle))
 	    __len = __half;
 	  else
 	    {
@@ -2025,8 +2061,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	_Tp, typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
 
-      return std::__upper_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__val_less_iter());
+      __decltype(__gnu_cxx::__ops::__less_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__less_val(__first, __val);
+      return std::__upper_bound(__first, __last, __val, __comp);
     }
 
   /**
@@ -2057,17 +2094,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_upper_pred(__first, __last,
 						__val, __comp);
 
-      return std::__upper_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+      return std::__upper_bound(__first, __last, __val, _GLIBCXX_MOVE(__comp));
     }
 
-  template<typename _ForwardIterator, typename _Tp,
-	   typename _CompareItTp, typename _CompareTpIt>
+  template<typename _ForwardIterator, typename _Tp, typename _Comp>
     _GLIBCXX20_CONSTEXPR
     pair<_ForwardIterator, _ForwardIterator>
     __equal_range(_ForwardIterator __first, _ForwardIterator __last,
-		  const _Tp& __val,
-		  _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it)
+		  const _Tp& __val, _GLIBCXX_FWDREF(_Comp) __comp)
     {
       typedef typename iterator_traits<_ForwardIterator>::difference_type
 	_DistanceType;
@@ -2079,21 +2113,22 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  _DistanceType __half = __len >> 1;
 	  _ForwardIterator __middle = __first;
 	  std::advance(__middle, __half);
-	  if (__comp_it_val(__middle, __val))
+	  if (__comp(*__middle, __val))
 	    {
 	      __first = __middle;
 	      ++__first;
 	      __len = __len - __half - 1;
 	    }
-	  else if (__comp_val_it(__val, __middle))
+	  else if (__comp(__val, *__middle))
 	    __len = __half;
 	  else
 	    {
 	      _ForwardIterator __left
-		= std::__lower_bound(__first, __middle, __val, __comp_it_val);
+		= std::__lower_bound(__first, __middle, __val, __comp);
 	      std::advance(__first, __len);
 	      _ForwardIterator __right
-		= std::__upper_bound(++__middle, __first, __val, __comp_val_it);
+		= std::__upper_bound(++__middle, __first, __val,
+				     _GLIBCXX_FORWARD(_Comp, __comp));
 	      return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
 	    }
 	}
@@ -2132,9 +2167,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
 
-      return std::__equal_range(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_less_val(),
-				__gnu_cxx::__ops::__val_less_iter());
+      __decltype(__gnu_cxx::__ops::__less_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__less_val(__first, __val);
+      return std::__equal_range(__first, __last, __val, __comp);
     }
 
   /**
@@ -2171,9 +2206,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_upper_pred(__first, __last,
 						__val, __comp);
 
-      return std::__equal_range(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_comp_val(__comp),
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+      return std::__equal_range(__first, __last, __val, _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -2201,9 +2234,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
 
-      _ForwardIterator __i
-	= std::__lower_bound(__first, __last, __val,
-			     __gnu_cxx::__ops::__iter_less_val());
+      __decltype(__gnu_cxx::__ops::__less_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__less_val(__first, __val);
+      _ForwardIterator __i =
+	std::__lower_bound(__first, __last, __val, __comp);
       return __i != __last && !(__val < *__i);
     }
 
@@ -2238,8 +2272,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 						__val, __comp);
 
       _ForwardIterator __i
-	= std::__lower_bound(__first, __last, __val,
-			     __gnu_cxx::__ops::__iter_comp_val(__comp));
+	= std::__lower_bound(__first, __last, __val, __comp);
       return __i != __last && !bool(__comp(__val, *__i));
     }
 
@@ -2251,11 +2284,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
 			  _InputIterator2 __first2, _InputIterator2 __last2,
-			  _OutputIterator __result, _Compare __comp)
+			  _OutputIterator __result,
+			  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2280,7 +2314,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 				   _BidirectionalIterator2 __first2,
 				   _BidirectionalIterator2 __last2,
 				   _BidirectionalIterator3 __result,
-				   _Compare __comp)
+				   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first1 == __last1)
 	{
@@ -2294,7 +2328,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       --__last2;
       while (true)
 	{
-	  if (__comp(__last2, __last1))
+	  if (__comp(*__last2, *__last1))
 	    {
 	      *--__result = _GLIBCXX_MOVE(*__last1);
 	      if (__first1 == __last1)
@@ -2360,19 +2394,25 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 		     _BidirectionalIterator __middle,
 		     _BidirectionalIterator __last,
 		     _Distance __len1, _Distance __len2,
-		     _Pointer __buffer, _Compare __comp)
+		     _Pointer __buffer, _GLIBCXX_FWDREF(_Compare) __comp)
     {
+      __decltype(__gnu_cxx::__ops::__less(_GLIBCXX_FORWARD(_Compare, __comp),
+					  __first, __buffer)) __cmp
+	= __gnu_cxx::__ops::__less(_GLIBCXX_FORWARD(_Compare, __comp),
+				   __first, __buffer);
       if (__len1 <= __len2)
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
-	  std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
-				     __first, __comp);
+	  std::__move_merge_adaptive
+	    (__buffer, __buffer_end, __middle, __last, __first,
+	     _GLIBCXX_FORWARD(_Compare, __cmp));
 	}
       else
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
-	  std::__move_merge_adaptive_backward(__first, __middle, __buffer,
-					      __buffer_end, __last, __comp);
+	  std::__move_merge_adaptive_backward
+	    (__first, __middle, __buffer, __buffer_end, __last,
+	     _GLIBCXX_FORWARD(_Compare, __cmp));
 	}
     }
 
@@ -2384,13 +2424,16 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 			    _BidirectionalIterator __last,
 			    _Distance __len1, _Distance __len2,
 			    _Pointer __buffer, _Distance __buffer_size,
-			    _Compare __comp)
+			    _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__len1 <= __buffer_size || __len2 <= __buffer_size)
-	std::__merge_adaptive(__first, __middle, __last,
-			      __len1, __len2, __buffer, __comp);
+	std::__merge_adaptive
+	  (__first, __middle, __last, __len1, __len2, __buffer,
+	   _GLIBCXX_FORWARD(_Compare, __comp));
       else
 	{
+	  typedef typename
+	    std::iterator_traits<_BidirectionalIterator>::value_type _Val;
 	  _BidirectionalIterator __first_cut = __first;
 	  _BidirectionalIterator __second_cut = __middle;
 	  _Distance __len11 = 0;
@@ -2399,18 +2442,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	    {
 	      __len11 = __len1 / 2;
 	      std::advance(__first_cut, __len11);
-	      __second_cut
-		= std::__lower_bound(__middle, __last, *__first_cut,
-				     __gnu_cxx::__ops::__iter_comp_val(__comp));
+	      const _Val& __val = *__first_cut;
+	      __second_cut =
+		std::__lower_bound(__middle, __last, __val, __comp);
 	      __len22 = std::distance(__middle, __second_cut);
 	    }
 	  else
 	    {
 	      __len22 = __len2 / 2;
 	      std::advance(__second_cut, __len22);
-	      __first_cut
-		= std::__upper_bound(__first, __middle, *__second_cut,
-				     __gnu_cxx::__ops::__val_comp_iter(__comp));
+	      const _Val& __val = *__second_cut;
+	      __first_cut =
+		std::__upper_bound(__first, __middle, __val, __comp);
 	      __len11 = std::distance(__first, __first_cut);
 	    }
 
@@ -2424,7 +2467,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  std::__merge_adaptive_resize(__new_middle, __second_cut, __last,
 				       _Distance(__len1 - __len11),
 				       _Distance(__len2 - __len22),
-				       __buffer, __buffer_size, __comp);
+				       __buffer, __buffer_size,
+				       _GLIBCXX_FORWARD(_Compare, __comp));
 	}
     }
 
@@ -2436,18 +2480,20 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 			   _BidirectionalIterator __middle,
 			   _BidirectionalIterator __last,
 			   _Distance __len1, _Distance __len2,
-			   _Compare __comp)
+			   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__len1 == 0 || __len2 == 0)
 	return;
 
       if (__len1 + __len2 == 2)
 	{
-	  if (__comp(__middle, __first))
+	  if (__comp(*__middle, *__first))
 	    std::iter_swap(__first, __middle);
 	  return;
 	}
 
+      typedef
+	typename std::iterator_traits<_BidirectionalIterator>::value_type _Val;
       _BidirectionalIterator __first_cut = __first;
       _BidirectionalIterator __second_cut = __middle;
       _Distance __len11 = 0;
@@ -2456,18 +2502,16 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  __len11 = __len1 / 2;
 	  std::advance(__first_cut, __len11);
-	  __second_cut
-	    = std::__lower_bound(__middle, __last, *__first_cut,
-				 __gnu_cxx::__ops::__iter_comp_val(__comp));
+	  const _Val& __val = *__first_cut;
+	  __second_cut = std::__lower_bound(__middle, __last, __val, __comp);
 	  __len22 = std::distance(__middle, __second_cut);
 	}
       else
 	{
 	  __len22 = __len2 / 2;
 	  std::advance(__second_cut, __len22);
-	  __first_cut
-	    = std::__upper_bound(__first, __middle, *__second_cut,
-				 __gnu_cxx::__ops::__val_comp_iter(__comp));
+	  const _Val& __val = *__second_cut;
+	  __first_cut = std::__upper_bound(__first, __middle, __val, __comp);
 	  __len11 = std::distance(__first, __first_cut);
 	}
 
@@ -2476,7 +2520,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       std::__merge_without_buffer(__first, __first_cut, __new_middle,
 				  __len11, __len22, __comp);
       std::__merge_without_buffer(__new_middle, __second_cut, __last,
-				  __len1 - __len11, __len2 - __len22, __comp);
+				  __len1 - __len11, __len2 - __len22,
+				  _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   template<typename _BidirectionalIterator, typename _Compare>
@@ -2484,7 +2529,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __inplace_merge(_BidirectionalIterator __first,
 		    _BidirectionalIterator __middle,
 		    _BidirectionalIterator __last,
-		    _Compare __comp)
+		    _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_BidirectionalIterator>::value_type
 	  _ValueType;
@@ -2505,17 +2550,21 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       if (__builtin_expect(__buf.size() == __buf.requested_size(), true))
 	std::__merge_adaptive
-	  (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp);
+	  (__first, __middle, __last, __len1, __len2, __buf.begin(),
+	   _GLIBCXX_FORWARD(_Compare, __comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
 	std::__merge_without_buffer
-	  (__first, __middle, __last, __len1, __len2, __comp);
+	  (__first, __middle, __last, __len1, __len2,
+	   _GLIBCXX_FORWARD(_Compare, __comp));
       else
 	std::__merge_adaptive_resize
 	  (__first, __middle, __last, __len1, __len2, __buf.begin(),
-	   _DistanceType(__buf.size()), __comp);
+	   _DistanceType(__buf.size()),
+	   _GLIBCXX_FORWARD(_Compare, __comp));
 #else
       std::__merge_without_buffer
-	(__first, __middle, __last, __len1, __len2, __comp);
+	(__first, __middle, __last, __len1, __len2,
+	 _GLIBCXX_FORWARD(_Compare, __comp));
 #endif
     }
 
@@ -2552,8 +2601,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_sorted(__middle, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      std::__inplace_merge(__first, __middle, __last,
-			   __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      std::__inplace_merge(__first, __middle, __last, __comp);
     }
 
   /**
@@ -2595,8 +2645,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_sorted_pred(__middle, __last, __comp);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      std::__inplace_merge(__first, __middle, __last,
-			   __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      std::__inplace_merge(__first, __middle, __last, _GLIBCXX_MOVE(__comp));
     }
 
 
@@ -2606,11 +2655,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _OutputIterator
     __move_merge(_InputIterator __first1, _InputIterator __last1,
 		 _InputIterator __first2, _InputIterator __last2,
-		 _OutputIterator __result, _Compare __comp)
+		 _OutputIterator __result, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2623,8 +2672,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  ++__result;
 	}
       return _GLIBCXX_MOVE3(__first2, __last2,
-			    _GLIBCXX_MOVE3(__first1, __last1,
-					   __result));
+			    _GLIBCXX_MOVE3(__first1, __last1, __result));
     }
 
   template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
@@ -2633,7 +2681,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __merge_sort_loop(_RandomAccessIterator1 __first,
 		      _RandomAccessIterator1 __last,
 		      _RandomAccessIterator2 __result, _Distance __step_size,
-		      _Compare __comp)
+		      _GLIBCXX_FWDREF(_Compare) __comp)
     {
       const _Distance __two_step = 2 * __step_size;
 
@@ -2648,7 +2696,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __step_size = std::min(_Distance(__last - __first), __step_size);
 
       std::__move_merge(__first, __first + __step_size,
-			__first + __step_size, __last, __result, __comp);
+			__first + __step_size, __last, __result,
+			_GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   template<typename _RandomAccessIterator, typename _Distance,
@@ -2657,14 +2706,16 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __chunk_insertion_sort(_RandomAccessIterator __first,
 			   _RandomAccessIterator __last,
-			   _Distance __chunk_size, _Compare __comp)
+			   _Distance __chunk_size,
+			   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__last - __first >= __chunk_size)
 	{
 	  std::__insertion_sort(__first, __first + __chunk_size, __comp);
 	  __first += __chunk_size;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort
+	(__first, __last, _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   enum { _S_chunk_size = 7 };
@@ -2673,7 +2724,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     void
     __merge_sort_with_buffer(_RandomAccessIterator __first,
 			     _RandomAccessIterator __last,
-			     _Pointer __buffer, _Compare __comp)
+			     _Pointer __buffer,
+			     _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
 	_Distance;
@@ -2686,11 +2738,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       while (__step_size < __len)
 	{
-	  std::__merge_sort_loop(__first, __last, __buffer,
-				 __step_size, __comp);
+	  std::__merge_sort_loop
+	    (__first, __last, __buffer, __step_size, __comp);
 	  __step_size *= 2;
-	  std::__merge_sort_loop(__buffer, __buffer_last, __first,
-				 __step_size, __comp);
+	  std::__merge_sort_loop
+	    (__buffer, __buffer_last, __first, __step_size, __comp);
 	  __step_size *= 2;
 	}
     }
@@ -2700,14 +2752,16 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __stable_sort_adaptive(_RandomAccessIterator __first,
 			   _RandomAccessIterator __middle,
 			   _RandomAccessIterator __last,
-			   _Pointer __buffer, _Compare __comp)
+			   _Pointer __buffer, _GLIBCXX_FWDREF(_Compare) __comp)
     {
-      std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp);
-      std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp);
+      __decltype(__gnu_cxx::__ops::__less(__comp, __first, __buffer)) __cmp
+	= __gnu_cxx::__ops::__less(__comp, __first, __buffer);
+      std::__merge_sort_with_buffer(__first, __middle, __buffer, __cmp);
+      std::__merge_sort_with_buffer(__middle, __last, __buffer, __cmp);
 
       std::__merge_adaptive(__first, __middle, __last,
 			    __middle - __first, __last - __middle,
-			    __buffer, __comp);
+			    __buffer, _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   template<typename _RandomAccessIterator, typename _Pointer,
@@ -2716,36 +2770,38 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __stable_sort_adaptive_resize(_RandomAccessIterator __first,
 				  _RandomAccessIterator __last,
 				  _Pointer __buffer, _Distance __buffer_size,
-				  _Compare __comp)
+				  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       const _Distance __len = (__last - __first + 1) / 2;
       const _RandomAccessIterator __middle = __first + __len;
       if (__len > __buffer_size)
 	{
-	  std::__stable_sort_adaptive_resize(__first, __middle, __buffer,
-					     __buffer_size, __comp);
-	  std::__stable_sort_adaptive_resize(__middle, __last, __buffer,
-					     __buffer_size, __comp);
-	  std::__merge_adaptive_resize(__first, __middle, __last,
-				       _Distance(__middle - __first),
-				       _Distance(__last - __middle),
-				       __buffer, __buffer_size,
-				       __comp);
+	  std::__stable_sort_adaptive_resize
+	    (__first, __middle, __buffer, __buffer_size, __comp);
+	  std::__stable_sort_adaptive_resize
+	    (__middle, __last, __buffer, __buffer_size, __comp);
+	  std::__merge_adaptive_resize
+	    (__first, __middle, __last,
+	     _Distance(__middle - __first), _Distance(__last - __middle),
+	     __buffer, __buffer_size, _GLIBCXX_FORWARD(_Compare, __comp));
 	}
       else
-	std::__stable_sort_adaptive(__first, __middle, __last,
-				    __buffer, __comp);
+	std::__stable_sort_adaptive
+	  (__first, __middle, __last, __buffer,
+	   _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   /// This is a helper function for the stable sorting routines.
   template<typename _RandomAccessIterator, typename _Compare>
     void
     __inplace_stable_sort(_RandomAccessIterator __first,
-			  _RandomAccessIterator __last, _Compare __comp)
+			  _RandomAccessIterator __last,
+			  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__last - __first < 15)
 	{
-	  std::__insertion_sort(__first, __last, __comp);
+	  std::__insertion_sort
+	    (__first, __last, _GLIBCXX_FORWARD(_Compare, __comp));
 	  return;
 	}
       _RandomAccessIterator __middle = __first + (__last - __first) / 2;
@@ -2754,7 +2810,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       std::__merge_without_buffer(__first, __middle, __last,
 				  __middle - __first,
 				  __last - __middle,
-				  __comp);
+				  _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   // stable_sort
@@ -2770,13 +2826,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     bool
     __includes(_InputIterator1 __first1, _InputIterator1 __last1,
 	       _InputIterator2 __first2, _InputIterator2 __last2,
-	       _Compare __comp)
+	       _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    return false;
-	  if (!__comp(__first1, __first2))
+	  if (!__comp(*__first1, *__first2))
 	    ++__first2;
 	  ++__first1;
 	}
@@ -2822,8 +2878,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return std::__includes(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return std::__includes(__first1, __last1, __first2, __last2, __comp);
     }
 
   /**
@@ -2870,7 +2927,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
       return std::__includes(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_comp_iter(__comp));
+			     _GLIBCXX_MOVE(__comp));
     }
 
   // nth_element
@@ -2887,7 +2944,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX20_CONSTEXPR
     bool
     __next_permutation(_BidirectionalIterator __first,
-		       _BidirectionalIterator __last, _Compare __comp)
+		       _BidirectionalIterator __last,
+		       _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first == __last)
 	return false;
@@ -2902,10 +2960,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  _BidirectionalIterator __ii = __i;
 	  --__i;
-	  if (__comp(__i, __ii))
+	  if (__comp(*__i, *__ii))
 	    {
 	      _BidirectionalIterator __j = __last;
-	      while (!__comp(__i, --__j))
+	      while (!__comp(*__i, *(--__j)))
 		{}
 	      std::iter_swap(__i, __j);
 	      std::__reverse(__ii, __last,
@@ -2947,8 +3005,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return std::__next_permutation
-	(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      return std::__next_permutation(__first, __last, __comp);
     }
 
   /**
@@ -2981,15 +3040,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return std::__next_permutation
-	(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return std::__next_permutation(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _BidirectionalIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     bool
     __prev_permutation(_BidirectionalIterator __first,
-		       _BidirectionalIterator __last, _Compare __comp)
+		       _BidirectionalIterator __last,
+		       _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first == __last)
 	return false;
@@ -3004,10 +3063,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  _BidirectionalIterator __ii = __i;
 	  --__i;
-	  if (__comp(__ii, __i))
+	  if (__comp(*__ii, *__i))
 	    {
 	      _BidirectionalIterator __j = __last;
-	      while (!__comp(--__j, __i))
+	      while (!__comp(*(--__j), *__i))
 		{}
 	      std::iter_swap(__i, __j);
 	      std::__reverse(__ii, __last,
@@ -3050,8 +3109,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return std::__prev_permutation(__first, __last,
-				     __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      return std::__prev_permutation(__first, __last, __comp);
     }
 
   /**
@@ -3084,8 +3144,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return std::__prev_permutation(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return std::__prev_permutation(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   // replace
@@ -3097,10 +3156,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _OutputIterator
     __replace_copy_if(_InputIterator __first, _InputIterator __last,
 		      _OutputIterator __result,
-		      _Predicate __pred, const _Tp& __new_value)
+		      _GLIBCXX_FWDREF(_Predicate) __pred,
+		      const _Tp& __new_value)
     {
       for (; __first != __last; ++__first, (void)++__result)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  *__result = __new_value;
 	else
 	  *__result = *__first;
@@ -3136,9 +3196,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	    typename iterator_traits<_InputIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__replace_copy_if(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_equals_val(__old_value),
-					      __new_value);
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __old_value)) __pred =
+	__gnu_cxx::__ops::__equal_val(__first, __old_value);
+      return std::__replace_copy_if
+	(__first, __last, __result, __pred, __new_value);
     }
 
   /**
@@ -3173,8 +3234,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__replace_copy_if(__first, __last, __result,
-				__gnu_cxx::__ops::__pred_iter(__pred),
-					      __new_value);
+				    _GLIBCXX_MOVE(__pred), __new_value);
     }
 
 #if __cplusplus >= 201103L
@@ -3205,20 +3265,22 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     inline bool
     is_sorted(_ForwardIterator __first, _ForwardIterator __last,
 	      _Compare __comp)
-    { return std::is_sorted_until(__first, __last, __comp) == __last; }
+    {
+      return std::is_sorted_until(__first, __last, std::move(__comp)) == __last;
+    }
 
   template<typename _ForwardIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
-		      _Compare __comp)
+		      _Compare&& __comp)
     {
       if (__first == __last)
 	return __last;
 
       _ForwardIterator __next = __first;
       for (++__next; __next != __last; __first = __next, (void)++__next)
-	if (__comp(__next, __first))
+	if (__comp(*__next, *__first))
 	  return __next;
       return __next;
     }
@@ -3244,7 +3306,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__is_sorted_until(__first, __last,
-				    __gnu_cxx::__ops::__iter_less_iter());
+				    __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3270,8 +3332,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return std::__is_sorted_until(__first, __last,
-				    __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return std::__is_sorted_until(__first, __last, std::move(__comp));
     }
 
   /**
@@ -3316,7 +3377,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     _GLIBCXX14_CONSTEXPR
     pair<_ForwardIterator, _ForwardIterator>
     __minmax_element(_ForwardIterator __first, _ForwardIterator __last,
-		     _Compare __comp)
+		     _Compare&& __comp)
     {
       _ForwardIterator __next = __first;
       if (__first == __last
@@ -3324,7 +3385,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	return std::make_pair(__first, __first);
 
       _ForwardIterator __min{}, __max{};
-      if (__comp(__next, __first))
+      if (__comp(*__next, *__first))
 	{
 	  __min = __next;
 	  __max = __first;
@@ -3343,25 +3404,25 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  __next = __first;
 	  if (++__next == __last)
 	    {
-	      if (__comp(__first, __min))
+	      if (__comp(*__first, *__min))
 		__min = __first;
-	      else if (!__comp(__first, __max))
+	      else if (!__comp(*__first, *__max))
 		__max = __first;
 	      break;
 	    }
 
-	  if (__comp(__next, __first))
+	  if (__comp(*__next, *__first))
 	    {
-	      if (__comp(__next, __min))
+	      if (__comp(*__next, *__min))
 		__min = __next;
-	      if (!__comp(__first, __max))
+	      if (!__comp(*__first, *__max))
 		__max = __first;
 	    }
 	  else
 	    {
-	      if (__comp(__first, __min))
+	      if (__comp(*__first, *__min))
 		__min = __first;
-	      if (!__comp(__next, __max))
+	      if (!__comp(*__next, *__max))
 		__max = __next;
 	    }
 
@@ -3396,7 +3457,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__minmax_element(__first, __last,
-				   __gnu_cxx::__ops::__iter_less_iter());
+				   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3425,8 +3486,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return std::__minmax_element(__first, __last,
-				   __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return std::__minmax_element(__first, __last, std::move(__comp));
     }
 
   template<typename _Tp>
@@ -3437,7 +3497,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__l.begin(), __l.end());
       pair<const _Tp*, const _Tp*> __p =
 	std::__minmax_element(__l.begin(), __l.end(),
-			      __gnu_cxx::__ops::__iter_less_iter());
+			      __gnu_cxx::__ops::__less());
       return std::make_pair(*__p.first, *__p.second);
     }
 
@@ -3448,8 +3508,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
       pair<const _Tp*, const _Tp*> __p =
-	std::__minmax_element(__l.begin(), __l.end(),
-			      __gnu_cxx::__ops::__iter_comp_iter(__comp));
+	std::__minmax_element(__l.begin(), __l.end(), std::move(__comp));
       return std::make_pair(*__p.first, *__p.second);
     }
 
@@ -3483,7 +3542,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first1, __last1);
 
       return std::__is_permutation(__first1, __last1, __first2,
-				   __gnu_cxx::__ops::__iter_comp_iter(__pred));
+				   std::move(__pred));
     }
 
 #if __cplusplus > 201103L
@@ -3493,7 +3552,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     bool
     __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
 		     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-		     _BinaryPredicate __pred)
+		     _BinaryPredicate&& __pred)
     {
       using _Cat1
 	= typename iterator_traits<_ForwardIterator1>::iterator_category;
@@ -3514,7 +3573,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       // have the same elements in the same order.
       for (; __first1 != __last1 && __first2 != __last2;
 	  ++__first1, (void)++__first2)
-	if (!__pred(__first1, __first2))
+	if (!__pred(*__first1, *__first2))
 	  break;
 
       if (__ra_iters)
@@ -3535,14 +3594,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
 	{
 	  if (__scan != std::__find_if(__first1, __scan,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
+		__gnu_cxx::__ops::__equal_ite(__pred, __first1, __scan)))
 	    continue; // We've seen this one before.
 
 	  auto __matches = std::__count_if(__first2, __last2,
-		__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
+	    __gnu_cxx::__ops::__equal_ite(__pred, __first2, __scan));
 	  if (0 == __matches
 	      || std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+		   __gnu_cxx::__ops::__equal_ite(__pred, __first1, __scan))
 	      != __matches)
 	    return false;
 	}
@@ -3573,7 +3632,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       return
 	std::__is_permutation(__first1, __last1, __first2, __last2,
-			      __gnu_cxx::__ops::__iter_equal_to_iter());
+			      __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -3602,7 +3661,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__is_permutation(__first1, __last1, __first2, __last2,
-				   __gnu_cxx::__ops::__iter_comp_iter(__pred));
+				   std::move(__pred));
     }
 #endif // C++14
 
@@ -3846,8 +3905,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_function_requires(_EqualOpConcept<
 		typename iterator_traits<_InputIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
-      return std::__find_if(__first, __last,
-			    __gnu_cxx::__ops::__iter_equals_val(__val));
+
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__equal_val(__first, __val);
+      return std::__find_if(__first, __last, __comp);
     }
 
   /**
@@ -3872,8 +3933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	      typename iterator_traits<_InputIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__find_if(__first, __last,
-			    __gnu_cxx::__ops::__pred_iter(__pred));
+      return std::__find_if(__first, __last, _GLIBCXX_MOVE(__pred));
     }
 
   /**
@@ -3977,8 +4037,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__adjacent_find(__first, __last,
-				  __gnu_cxx::__ops::__iter_equal_to_iter());
+      __decltype(__gnu_cxx::__ops::__equal_to(__first)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first);
+      return std::__adjacent_find(__first, __last, __comp);
     }
 
   /**
@@ -4006,7 +4067,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__adjacent_find(__first, __last,
-			__gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+				  _GLIBCXX_MOVE(__binary_pred));
     }
 
   /**
@@ -4029,8 +4090,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_InputIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__count_if(__first, __last,
-			     __gnu_cxx::__ops::__iter_equals_val(__value));
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __value)) __comp =
+	__gnu_cxx::__ops::__equal_val(__first, __value);
+      return std::__count_if(__first, __last, __comp);
     }
 
   /**
@@ -4053,8 +4115,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_InputIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__count_if(__first, __last,
-			     __gnu_cxx::__ops::__pred_iter(__pred));
+      return std::__count_if(__first, __last, _GLIBCXX_MOVE(__pred));
     }
 
   /**
@@ -4098,8 +4159,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      return std::__search(__first1, __last1, __first2, __last2,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+      __decltype(__gnu_cxx::__ops::__equal_to(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first1, __first2);
+      return std::__search(__first1, __last1, __first2, __last2, __comp);
     }
 
   /**
@@ -4129,8 +4191,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__search_n(__first, __last, __count,
-			     __gnu_cxx::__ops::__iter_equals_val(__val));
+      __decltype(__gnu_cxx::__ops::__equal_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__equal_val(__first, __val);
+      return std::__search_n(__first, __last, __count, __comp);
     }
 
 
@@ -4165,8 +4228,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__search_n(__first, __last, __count,
-		__gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
+      __decltype(__gnu_cxx::__ops::__comp_val
+		 (_GLIBCXX_MOVE(__binary_pred), __first, __val)) __unry_pred =
+	__gnu_cxx::__ops::__comp_val(_GLIBCXX_MOVE(__binary_pred),
+				     __first, __val);
+      return std::__search_n
+	(__first, __last, __count, _GLIBCXX_MOVE(__unry_pred));
     }
 
 #if __cplusplus >= 201703L
@@ -4422,10 +4489,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       if (__first == __last)
 	return __result;
-      return std::__unique_copy(__first, __last, __result,
-				__gnu_cxx::__ops::__iter_equal_to_iter(),
-				std::__iterator_category(__first),
-				std::__iterator_category(__result));
+
+      __decltype(__gnu_cxx::__ops::__equal_to(__first)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first);
+      return std::__unique_copy
+	(__first, __last, __result, __comp,
+	 std::__iterator_category(__first), std::__iterator_category(__result));
     }
 
   /**
@@ -4462,10 +4531,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       if (__first == __last)
 	return __result;
-      return std::__unique_copy(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
-				std::__iterator_category(__first),
-				std::__iterator_category(__result));
+      return std::__unique_copy
+	(__first, __last, __result, _GLIBCXX_MOVE(__binary_pred),
+	 std::__iterator_category(__first), std::__iterator_category(__result));
     }
 
 #if __cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED
@@ -4579,7 +4647,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_valid_range(__first, __last);
 
-      return std::__partition(__first, __last, __pred,
+      return std::__partition(__first, __last, _GLIBCXX_MOVE(__pred),
 			      std::__iterator_category(__first));
     }
 
@@ -4617,8 +4685,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__middle, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      std::__partial_sort(__first, __middle, __last,
-			  __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      std::__partial_sort(__first, __middle, __last, __comp);
     }
 
   /**
@@ -4658,8 +4727,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__middle, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      std::__partial_sort(__first, __middle, __last,
-			  __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      std::__partial_sort(__first, __middle, __last, _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -4695,9 +4763,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last || __nth == __last)
 	return;
 
-      std::__introselect(__first, __nth, __last,
-			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      std::__introselect
+	(__first, __nth, __last, std::__lg(__last - __first) * 2, __comp);
     }
 
   /**
@@ -4736,9 +4805,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last || __nth == __last)
 	return;
 
-      std::__introselect(__first, __nth, __last,
-			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      std::__introselect
+	(__first, __nth, __last, std::__lg(__last - __first) * 2,
+	 _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -4768,7 +4837,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      std::__sort(__first, __last, __comp);
     }
 
   /**
@@ -4801,7 +4872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      std::__sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -4810,11 +4881,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _OutputIterator
     __merge(_InputIterator1 __first1, _InputIterator1 __last1,
 	    _InputIterator2 __first2, _InputIterator2 __last2,
-	    _OutputIterator __result, _Compare __comp)
+	    _OutputIterator __result, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = *__first2;
 	      ++__first2;
@@ -4872,9 +4943,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__merge(__first1, __last1,
-				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return _GLIBCXX_STD_A::__merge
+	(__first1, __last1, __first2, __last2, __result, __comp);
     }
 
   /**
@@ -4923,15 +4995,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
-      return _GLIBCXX_STD_A::__merge(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__merge
+	(__first1, __last1, __first2, __last2, __result, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
     inline void
     __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		  _Compare __comp)
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	_ValueType;
@@ -4948,16 +5019,19 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       _TmpBuf __buf(__first, (__last - __first + 1) / 2);
 
       if (__builtin_expect(__buf.requested_size() == __buf.size(), true))
-	std::__stable_sort_adaptive(__first,
-				    __first + _DistanceType(__buf.size()),
-				    __last, __buf.begin(), __comp);
+	std::__stable_sort_adaptive
+	  (__first, __first + _DistanceType(__buf.size()), __last,
+	   __buf.begin(), _GLIBCXX_FORWARD(_Compare, __comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
-	std::__inplace_stable_sort(__first, __last, __comp);
+	std::__inplace_stable_sort
+	  (__first, __last, _GLIBCXX_FORWARD(_Compare, __comp));
       else
-	std::__stable_sort_adaptive_resize(__first, __last, __buf.begin(),
-					   _DistanceType(__buf.size()), __comp);
+	std::__stable_sort_adaptive_resize
+	  (__first, __last, __buf.begin(), _DistanceType(__buf.size()),
+	   _GLIBCXX_FORWARD(_Compare, __comp));
 #else
-      std::__inplace_stable_sort(__first, __last, __comp);
+      std::__inplace_stable_sort
+	(__first, __last, _GLIBCXX_FORWARD(_Compare, __comp));
 #endif
     }
 
@@ -4990,8 +5064,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      _GLIBCXX_STD_A::__stable_sort(__first, __last, __comp);
     }
 
   /**
@@ -5026,8 +5101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      _GLIBCXX_STD_A::__stable_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5037,16 +5111,16 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _OutputIterator
     __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
 		_InputIterator2 __first2, _InputIterator2 __last2,
-		_OutputIterator __result, _Compare __comp)
+		_OutputIterator __result, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first1, __first2))
+	  if (__comp(*__first1, *__first2))
 	    {
 	      *__result = *__first1;
 	      ++__first1;
 	    }
-	  else if (__comp(__first2, __first1))
+	  else if (__comp(*__first2, *__first1))
 	    {
 	      *__result = *__first2;
 	      ++__first2;
@@ -5108,9 +5182,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__set_union(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return _GLIBCXX_STD_A::__set_union
+	(__first1, __last1, __first2, __last2, __result, __comp);
     }
 
   /**
@@ -5159,9 +5234,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
-      return _GLIBCXX_STD_A::__set_union(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__set_union
+	(__first1, __last1, __first2, __last2, __result, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5171,12 +5245,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _OutputIterator
     __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
 		       _InputIterator2 __first2, _InputIterator2 __last2,
-		       _OutputIterator __result, _Compare __comp)
+		       _OutputIterator __result,
+		       _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(__first1, __first2))
+	if (__comp(*__first1, *__first2))
 	  ++__first1;
-	else if (__comp(__first2, __first1))
+	else if (__comp(*__first2, *__first1))
 	  ++__first2;
 	else
 	  {
@@ -5230,9 +5305,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
-				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return _GLIBCXX_STD_A::__set_intersection
+	(__first1, __last1, __first2, __last2, __result, __comp);
     }
 
   /**
@@ -5280,9 +5356,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
-      return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__set_intersection
+	(__first1, __last1, __first2, __last2, __result, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5292,16 +5367,16 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _OutputIterator
     __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
 		     _InputIterator2 __first2, _InputIterator2 __last2,
-		     _OutputIterator __result, _Compare __comp)
+		     _OutputIterator __result, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(__first1, __first2))
+	if (__comp(*__first1, *__first2))
 	  {
 	    *__result = *__first1;
 	    ++__first1;
 	    ++__result;
 	  }
-	else if (__comp(__first2, __first1))
+	else if (__comp(*__first2, *__first1))
 	  ++__first2;
 	else
 	  {
@@ -5355,9 +5430,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
-				   __first2, __last2, __result,
-				   __gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return _GLIBCXX_STD_A::__set_difference
+	(__first1, __last1, __first2, __last2, __result, __comp);
     }
 
   /**
@@ -5407,9 +5483,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
-      return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
-				   __first2, __last2, __result,
-				   __gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__set_difference
+	(__first1, __last1, __first2, __last2, __result, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5422,16 +5497,16 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 			       _InputIterator2 __first2,
 			       _InputIterator2 __last2,
 			       _OutputIterator __result,
-			       _Compare __comp)
+			       _GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__first1 != __last1 && __first2 != __last2)
-	if (__comp(__first1, __first2))
+	if (__comp(*__first1, *__first2))
 	  {
 	    *__result = *__first1;
 	    ++__first1;
 	    ++__result;
 	  }
-	else if (__comp(__first2, __first1))
+	else if (__comp(*__first2, *__first1))
 	  {
 	    *__result = *__first2;
 	    ++__first2;
@@ -5490,9 +5565,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
-					__first2, __last2, __result,
-					__gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__less(__first1, __first2);
+      return _GLIBCXX_STD_A::__set_symmetric_difference
+	(__first1, __last1, __first2, __last2, __result, __comp);
     }
 
   /**
@@ -5543,22 +5619,21 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
-      return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__set_symmetric_difference
+	(__first1, __last1, __first2, __last2, __result, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
     _GLIBCXX14_CONSTEXPR
     _ForwardIterator
     __min_element(_ForwardIterator __first, _ForwardIterator __last,
-		  _Compare __comp)
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first == __last)
 	return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__first, __result))
+	if (__comp(*__first, *__result))
 	  __result = __first;
       return __result;
     }
@@ -5582,8 +5657,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      return _GLIBCXX_STD_A::__min_element(__first, __last, __comp);
     }
 
   /**
@@ -5609,20 +5685,20 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__min_element
+	(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
     _GLIBCXX14_CONSTEXPR
     _ForwardIterator
     __max_element(_ForwardIterator __first, _ForwardIterator __last,
-		  _Compare __comp)
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first == __last) return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__result, __first))
+	if (__comp(*__result, *__first))
 	  __result = __first;
       return __result;
     }
@@ -5646,8 +5722,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
+      return _GLIBCXX_STD_A::__max_element(__first, __last, __comp);
     }
 
   /**
@@ -5673,8 +5750,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+      return _GLIBCXX_STD_A::__max_element
+	(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -5686,7 +5763,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       __glibcxx_requires_irreflexive(__l.begin(), __l.end());
       return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(),
-	  __gnu_cxx::__ops::__iter_less_iter());
+					    __gnu_cxx::__ops::__less());
     }
 
   template<typename _Tp, typename _Compare>
@@ -5696,7 +5773,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
       return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(),
-	  __gnu_cxx::__ops::__iter_comp_iter(__comp));
+					    std::move(__comp));
     }
 
   template<typename _Tp>
@@ -5706,7 +5783,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       __glibcxx_requires_irreflexive(__l.begin(), __l.end());
       return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(),
-	  __gnu_cxx::__ops::__iter_less_iter());
+					    __gnu_cxx::__ops::__less());
     }
 
   template<typename _Tp, typename _Compare>
@@ -5716,7 +5793,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp);
       return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(),
-	  __gnu_cxx::__ops::__iter_comp_iter(__comp));
+					    std::move(__comp));
     }
 #endif // C++11
 
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d831e0e9883..9b8e2c6a56d 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1316,7 +1316,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
     bool
     __lexicographical_compare_impl(_II1 __first1, _II1 __last1,
 				   _II2 __first2, _II2 __last2,
-				   _Compare __comp)
+				   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_II1>::iterator_category _Category1;
       typedef typename iterator_traits<_II2>::iterator_category _Category2;
@@ -1326,9 +1326,9 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
       for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
 	   ++__first1, (void)++__first2)
 	{
-	  if (__comp(__first1, __first2))
+	  if (__comp(*__first1, *__first2))
 	    return true;
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    return false;
 	}
       return __first1 == __last1 && __first2 != __last2;
@@ -1342,10 +1342,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 	static bool
 	__lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2)
 	{
-	  using __gnu_cxx::__ops::__iter_less_iter;
-	  return std::__lexicographical_compare_impl(__first1, __last1,
-						     __first2, __last2,
-						     __iter_less_iter());
+	  __decltype(__gnu_cxx::__ops::__less(__first1, __first2)) __comp =
+	    __gnu_cxx::__ops::__less(__first1, __first2);
+	  return std::__lexicographical_compare_impl
+	    (__first1, __last1, __first2, __last2, __comp);
 	}
 
       template<typename _II1, typename _II2>
@@ -1486,7 +1486,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
-		  const _Tp& __val, _Compare __comp)
+		  const _Tp& __val, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_ForwardIterator>::difference_type
 	_DistanceType;
@@ -1498,7 +1498,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 	  _DistanceType __half = __len >> 1;
 	  _ForwardIterator __middle = __first;
 	  std::advance(__middle, __half);
-	  if (__comp(__middle, __val))
+	  if (__comp(*__middle, __val))
 	    {
 	      __first = __middle;
 	      ++__first;
@@ -1533,8 +1533,9 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
 
-      return std::__lower_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_less_val());
+      __decltype(__gnu_cxx::__ops::__less_val(__first, __val)) __comp =
+	__gnu_cxx::__ops::__less_val(__first, __val);
+      return std::__lower_bound(__first, __last, __val, __comp);
     }
 
   /// This is a helper function for the sort routines and for random.tcc.
@@ -1650,7 +1651,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _GLIBCXX20_CONSTEXPR
     inline bool
     __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2,
-	     _BinaryPredicate __binary_pred)
+	     _BinaryPredicate&& __binary_pred)
     {
       using _RATag = random_access_iterator_tag;
       using _Cat1 = typename iterator_traits<_II1>::iterator_category;
@@ -1662,8 +1663,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	  auto __d2 = std::distance(__first2, __last2);
 	  if (__d1 != __d2)
 	    return false;
-	  return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
-				       __binary_pred);
+	  return _GLIBCXX_STD_A::equal
+	    (__first1, __last1, __first2,
+	     std::forward<_BinaryPredicate>(__binary_pred));
 	}
 
       for (; __first1 != __last1 && __first2 != __last2;
@@ -1734,7 +1736,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2,
-				      __binary_pred);
+				      std::move(__binary_pred));
     }
 #endif // __glibcxx_robust_nonmodifying_seq_ops
 
@@ -1801,8 +1803,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__lexicographical_compare_impl
-	(__first1, __last1, __first2, __last2,
-	 __gnu_cxx::__ops::__iter_comp_iter(__comp));
+	(__first1, __last1, __first2, __last2, _GLIBCXX_MOVE(__comp));
     }
 
 #if __cpp_lib_three_way_comparison
@@ -1908,9 +1909,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _GLIBCXX20_CONSTEXPR
     pair<_InputIterator1, _InputIterator2>
     __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
-	       _InputIterator2 __first2, _BinaryPredicate __binary_pred)
+	       _InputIterator2 __first2,
+	       _GLIBCXX_FWDREF(_BinaryPredicate) __binary_pred)
     {
-      while (__first1 != __last1 && __binary_pred(__first1, __first2))
+      while (__first1 != __last1 && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -1945,8 +1947,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	    typename iterator_traits<_InputIterator2>::value_type>)
       __glibcxx_requires_valid_range(__first1, __last1);
 
-      return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+      __decltype(__gnu_cxx::__ops::__equal_to(__first1, __first2)) __comp =
+	__gnu_cxx::__ops::__equal_to(__first1, __first2);
+      return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __comp);
     }
 
   /**
@@ -1978,7 +1981,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
-	__gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+					_GLIBCXX_MOVE(__binary_pred));
     }
 
 #if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14
@@ -1988,10 +1991,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     pair<_InputIterator1, _InputIterator2>
     __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
 	       _InputIterator2 __first2, _InputIterator2 __last2,
-	       _BinaryPredicate __binary_pred)
+	       _BinaryPredicate&& __binary_pred)
     {
       while (__first1 != __last1 && __first2 != __last2
-	     && __binary_pred(__first1, __first2))
+	     && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -2028,8 +2031,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
 
-      return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+      return _GLIBCXX_STD_A::__mismatch
+	(__first1, __last1, __first2, __last2,
+	 __gnu_cxx::__ops::__equal_to(__first1, __first2));
     }
 
   /**
@@ -2064,7 +2068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+					_GLIBCXX_MOVE(__binary_pred));
     }
 #endif
 
@@ -2075,9 +2079,9 @@ _GLIBCXX_END_NAMESPACE_ALGO
     _GLIBCXX20_CONSTEXPR
     inline _InputIterator
     __find_if(_InputIterator __first, _InputIterator __last,
-	      _Predicate __pred, input_iterator_tag)
+	      _GLIBCXX_FWDREF(_Predicate) __pred, input_iterator_tag)
     {
-      while (__first != __last && !__pred(__first))
+      while (__first != __last && !__pred(*__first))
 	++__first;
       return __first;
     }
@@ -2087,26 +2091,26 @@ _GLIBCXX_END_NAMESPACE_ALGO
     _GLIBCXX20_CONSTEXPR
     _RandomAccessIterator
     __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	      _Predicate __pred, random_access_iterator_tag)
+	      _GLIBCXX_FWDREF(_Predicate) __pred, random_access_iterator_tag)
     {
       typename iterator_traits<_RandomAccessIterator>::difference_type
 	__trip_count = (__last - __first) >> 2;
 
       for (; __trip_count > 0; --__trip_count)
 	{
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 	}
@@ -2114,17 +2118,17 @@ _GLIBCXX_END_NAMESPACE_ALGO
       switch (__last - __first)
 	{
 	case 3:
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 	  // FALLTHRU
 	case 2:
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 	  // FALLTHRU
 	case 1:
-	  if (__pred(__first))
+	  if (__pred(*__first))
 	    return __first;
 	  ++__first;
 	  // FALLTHRU
@@ -2137,20 +2141,22 @@ _GLIBCXX_END_NAMESPACE_ALGO
   template<typename _Iterator, typename _Predicate>
     _GLIBCXX20_CONSTEXPR
     inline _Iterator
-    __find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
+    __find_if(_Iterator __first, _Iterator __last,
+	      _GLIBCXX_FWDREF(_Predicate) __pred)
     {
-      return __find_if(__first, __last, __pred,
+      return __find_if(__first, __last, _GLIBCXX_FORWARD(_Predicate, __pred),
 		       std::__iterator_category(__first));
     }
 
   template<typename _InputIterator, typename _Predicate>
     _GLIBCXX20_CONSTEXPR
     typename iterator_traits<_InputIterator>::difference_type
-    __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
+    __count_if(_InputIterator __first, _InputIterator __last,
+	       _GLIBCXX_FWDREF(_Predicate) __pred)
     {
       typename iterator_traits<_InputIterator>::difference_type __n = 0;
       for (; __first != __last; ++__first)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  ++__n;
       return __n;
     }
@@ -2159,7 +2165,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
     _GLIBCXX20_CONSTEXPR
     _ForwardIterator
     __remove_if(_ForwardIterator __first, _ForwardIterator __last,
-		_Predicate __pred)
+		_GLIBCXX_FWDREF(_Predicate) __pred)
     {
       __first = std::__find_if(__first, __last, __pred);
       if (__first == __last)
@@ -2167,7 +2173,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
       _ForwardIterator __result = __first;
       ++__first;
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = _GLIBCXX_MOVE(*__first);
 	    ++__result;
@@ -2181,7 +2187,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
     _ForwardIterator1
     __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
 	     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	     _BinaryPredicate  __predicate)
+	     _GLIBCXX_FWDREF(_BinaryPredicate)  __predicate)
     {
       // Test for empty ranges
       if (__first1 == __last1 || __first2 == __last2)
@@ -2190,18 +2196,25 @@ _GLIBCXX_END_NAMESPACE_ALGO
       // Test for a pattern of length 1.
       _ForwardIterator2 __p1(__first2);
       if (++__p1 == __last2)
-	return std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+	{
+	  __decltype(__gnu_cxx::__ops::__equal_ite
+		     (_GLIBCXX_FORWARD(_BinaryPredicate, __predicate),
+		      __first1, __first2)) __cmp =
+	    __gnu_cxx::__ops::__equal_ite
+	    (_GLIBCXX_FORWARD(_BinaryPredicate, __predicate),
+	     __first1, __first2);
+	  return std::__find_if(__first1, __last1, _GLIBCXX_MOVE(__cmp));
+	}
 
       // General case.
       _ForwardIterator1 __current = __first1;
 
+      __decltype(__gnu_cxx::__ops::__equal_ite(__predicate, __first1, __first2))
+	__unry_pred = __gnu_cxx::__ops::__equal_ite(__predicate,
+						    __first1, __first2);
       for (;;)
 	{
-	  __first1 =
-	    std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
-
+	  __first1 = std::__find_if(__first1, __last1, __unry_pred);
 	  if (__first1 == __last1)
 	    return __last1;
 
@@ -2210,7 +2223,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
 	  if (++__current == __last1)
 	    return __last1;
 
-	  while (__predicate(__current, __p))
+	  while (__predicate(*__current, *__p))
 	    {
 	      if (++__p == __last2)
 		return __first1;
@@ -2233,7 +2246,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
       // Efficiently compare identical prefixes:  O(N) if sequences
       // have the same elements in the same order.
       for (; __first1 != __last1; ++__first1, (void)++__first2)
-	if (!__pred(__first1, __first2))
+	if (!__pred(*__first1, *__first2))
 	  break;
 
       if (__first1 == __last1)
@@ -2246,15 +2259,14 @@ _GLIBCXX_END_NAMESPACE_ALGO
       for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
 	{
 	  if (__scan != std::__find_if(__first1, __scan,
-			  __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
+		__gnu_cxx::__ops::__equal_ite(__pred, __first1, __scan)))
 	    continue; // We've seen this one before.
 
-	  auto __matches
-	    = std::__count_if(__first2, __last2,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
+	  auto __matches = std::__count_if(__first2, __last2,
+		__gnu_cxx::__ops::__equal_ite(__pred, __first2, __scan));
 	  if (0 == __matches ||
 	      std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+		__gnu_cxx::__ops::__equal_ite(__pred, __first1, __scan))
 	      != __matches)
 	    return false;
 	}
@@ -2288,7 +2300,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
 
       return std::__is_permutation(__first1, __last1, __first2,
-				   __gnu_cxx::__ops::__iter_equal_to_iter());
+				   __gnu_cxx::__ops::__equal_to());
     }
 #endif // C++11
 
@@ -2333,7 +2345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__search(__first1, __last1, __first2, __last2,
-			   __gnu_cxx::__ops::__iter_comp_iter(__predicate));
+			   _GLIBCXX_MOVE(__predicate));
     }
 
 _GLIBCXX_END_NAMESPACE_ALGO
diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h
index 9c1214a2b21..78f8363f201 100644
--- a/libstdc++-v3/include/bits/stl_heap.h
+++ b/libstdc++-v3/include/bits/stl_heap.h
@@ -74,12 +74,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     _Distance
     __is_heap_until(_RandomAccessIterator __first, _Distance __n,
-		    _Compare& __comp)
+		    _GLIBCXX_FWDREF(_Compare) __comp)
     {
       _Distance __parent = 0;
       for (_Distance __child = 1; __child < __n; ++__child)
 	{
-	  if (__comp(__first + __parent, __first + __child))
+	  if (__comp(__first[__parent], __first[__child]))
 	    return __child;
 	  if ((__child & 1) == 0)
 	    ++__parent;
@@ -94,7 +94,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline bool
     __is_heap(_RandomAccessIterator __first, _Distance __n)
     {
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
       return std::__is_heap_until(__first, __n, __comp) == __n;
     }
 
@@ -102,11 +103,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	   typename _Distance>
     _GLIBCXX20_CONSTEXPR
     inline bool
-    __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
+    __is_heap(_RandomAccessIterator __first, _GLIBCXX_FWDREF(_Compare) __comp,
+	      _Distance __n)
     {
-      typedef __decltype(__comp) _Cmp;
-      __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
-      return std::__is_heap_until(__first, __n, __cmp) == __n;
+      return std::__is_heap_until
+	(__first, __n, _GLIBCXX_FORWARD(_Compare, __comp)) == __n;
     }
 
   template<typename _RandomAccessIterator>
@@ -119,9 +120,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     inline bool
     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	      _Compare __comp)
+	      _GLIBCXX_FWDREF(_Compare) __comp)
     {
-      return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
+      return std::__is_heap(__first, _GLIBCXX_FORWARD(_Compare, __comp),
 			    std::distance(__first, __last));
     }
 
@@ -133,17 +134,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __push_heap(_RandomAccessIterator __first,
-		_Distance __holeIndex, _Distance __topIndex, _Tp __value,
-		_Compare& __comp)
+		_Distance __holeIndex, _Distance __topIndex,
+#if __cplusplus >= 201103L
+		_Tp&& __value,
+#else
+		_Tp __value,
+#endif
+		_GLIBCXX_FWDREF(_Compare) __comp)
     {
       _Distance __parent = (__holeIndex - 1) / 2;
-      while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
+      while (__holeIndex > __topIndex && __comp(__first[__parent], __value))
 	{
 	  *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
 	  __holeIndex = __parent;
 	  __parent = (__holeIndex - 1) / 2;
 	}
-      *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
+      *(__first + __holeIndex) = _GLIBCXX_FORWARD(_Tp, __value);
     }
 
   /**
@@ -174,8 +180,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive(__first, __last);
       __glibcxx_requires_heap(__first, __last - 1);
 
-      __gnu_cxx::__ops::_Iter_less_val __comp;
       _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
+      __decltype(__gnu_cxx::__ops::__less_val(__first, __value)) __comp =
+	__gnu_cxx::__ops::__less_val(__first, __value);
       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
 		       _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
     }
@@ -210,11 +217,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
       __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
 
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
-	__cmp(_GLIBCXX_MOVE(__comp));
       _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
-		       _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
+		       _DistanceType(0), _GLIBCXX_MOVE(__value),
+		       _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Distance,
@@ -222,15 +228,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
-		  _Distance __len, _Tp __value, _Compare __comp)
+		  _Distance __len,
+#if __cplusplus >= 201103L
+		  _Tp&& __value,
+#else
+		  _Tp __value,
+#endif
+		  _GLIBCXX_FWDREF(_Compare) __comp)
     {
       const _Distance __topIndex = __holeIndex;
       _Distance __secondChild = __holeIndex;
       while (__secondChild < (__len - 1) / 2)
 	{
 	  __secondChild = 2 * (__secondChild + 1);
-	  if (__comp(__first + __secondChild,
-		     __first + (__secondChild - 1)))
+	  if (__comp(__first[__secondChild],
+		     __first[__secondChild - 1]))
 	    __secondChild--;
 	  *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
 	  __holeIndex = __secondChild;
@@ -242,17 +254,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 						     + (__secondChild - 1)));
 	  __holeIndex = __secondChild - 1;
 	}
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
-	__cmp(_GLIBCXX_MOVE(__comp));
+      __decltype(__gnu_cxx::__ops::__less_val(_GLIBCXX_FORWARD(_Compare, __comp),
+					      __first, __value)) __cmp =
+	__gnu_cxx::__ops::__less_val(_GLIBCXX_FORWARD(_Compare, __comp),
+				     __first, __value);
       std::__push_heap(__first, __holeIndex, __topIndex,
-		       _GLIBCXX_MOVE(__value), __cmp);
+		       _GLIBCXX_FORWARD(_Tp, __value),
+		       _GLIBCXX_FORWARD(_Compare, __cmp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     inline void
     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	       _RandomAccessIterator __result, _Compare& __comp)
+	       _RandomAccessIterator __result, _GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	_ValueType;
@@ -261,9 +276,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _ValueType __value = _GLIBCXX_MOVE(*__result);
       *__result = _GLIBCXX_MOVE(*__first);
-      std::__adjust_heap(__first, _DistanceType(0),
-			 _DistanceType(__last - __first),
-			 _GLIBCXX_MOVE(__value), __comp);
+      std::__adjust_heap
+	(__first, _DistanceType(0), _DistanceType(__last - __first),
+	 _GLIBCXX_MOVE(__value), _GLIBCXX_FORWARD(_Compare, __comp));
     }
 
   /**
@@ -295,7 +310,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__last - __first > 1)
 	{
 	  --__last;
-	  __gnu_cxx::__ops::_Iter_less_iter __comp;
+	  __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	    __gnu_cxx::__ops::__less(__first);
 	  std::__pop_heap(__first, __last, __last, __comp);
 	}
     }
@@ -327,10 +343,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       if (__last - __first > 1)
 	{
-	  typedef __decltype(__comp) _Cmp;
-	  __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
 	  --__last;
-	  std::__pop_heap(__first, __last, __last, __cmp);
+	  std::__pop_heap(__first, __last, __last, _GLIBCXX_MOVE(__comp));
 	}
     }
 
@@ -338,7 +352,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		_Compare& __comp)
+		_GLIBCXX_FWDREF(_Compare) __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	  _ValueType;
@@ -382,7 +396,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
       std::__make_heap(__first, __last, __comp);
     }
 
@@ -408,16 +423,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      typedef __decltype(__comp) _Cmp;
-      __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
-      std::__make_heap(__first, __last, __cmp);
+      std::__make_heap(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     void
     __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		_Compare& __comp)
+		_GLIBCXX_FWDREF(_Compare) __comp)
     {
       while (__last - __first > 1)
 	{
@@ -448,7 +461,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive(__first, __last);
       __glibcxx_requires_heap(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
+      __decltype(__gnu_cxx::__ops::__less(__first)) __comp =
+	__gnu_cxx::__ops::__less(__first);
       std::__sort_heap(__first, __last, __comp);
     }
 
@@ -475,9 +489,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
       __glibcxx_requires_heap_pred(__first, __last, __comp);
 
-      typedef __decltype(__comp) _Cmp;
-      __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
-      std::__sort_heap(__first, __last, __cmp);
+      std::__sort_heap(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -504,9 +516,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
       return __first + 
-	std::__is_heap_until(__first, std::distance(__first, __last), __comp);
+	std::__is_heap_until(__first, std::distance(__first, __last),
+			     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -532,10 +544,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
-      typedef __decltype(__comp) _Cmp;
-      __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
       return __first
-	+ std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
+	+ std::__is_heap_until(__first, std::distance(__first, __last),
+			       std::move(__comp));
     }
 
   /**
@@ -572,11 +583,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       const auto __dist = std::distance(__first, __last);
-      typedef __decltype(__comp) _Cmp;
-      __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
-      return std::__is_heap_until(__first, __dist, __cmp) == __dist;
+      return std::__is_heap_until(__first, __dist,
+				  std::move(__comp)) == __dist;
     }
-#endif
+#endif // C++11
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 978093fc587..9c7ec8a471b 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -461,7 +461,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 	template<typename _Arg>
 	  _Link_type
-	  operator()(_GLIBCXX_FWDREF(_Arg) __arg)
+	  operator()(_GLIBCXX_FWDCREF(_Arg) __arg)
 	  {
 	    _Link_type __node = static_cast<_Link_type>(_M_extract());
 	    if (__node)
@@ -523,7 +523,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 	template<typename _Arg>
 	  _Link_type
-	  operator()(_GLIBCXX_FWDREF(_Arg) __arg) const
+	  operator()(_GLIBCXX_FWDCREF(_Arg) __arg) const
 	  { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); }
 
       private:
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index 0bf8309c19a..b88da7fd930 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -64,7 +64,7 @@
 #include <bits/stl_construct.h>
 #include <bits/stl_uninitialized.h>
 #include <bits/stl_deque.h>
-#include <bits/refwrap.h>
+#include <bits/move.h>
 #include <bits/range_access.h>
 #include <bits/deque.tcc>
 
@@ -99,12 +99,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename deque<_Tp, _Alloc>::size_type
     erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
-      using namespace __gnu_cxx;
       _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __ucont = __cont;
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
-      auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__pred_iter(std::ref(__pred)));
+      auto __removed = std::__remove_if
+	(__ucont.begin(), __end, std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -123,8 +122,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __ucont = __cont;
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
-      auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+      auto __removed = std::__remove_if
+	(__ucont.begin(), __end, __ops::__equal_val(__value));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 99364286a72..8b2b136411d 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -58,6 +58,9 @@
 #if _GLIBCXX_HOSTED
 # include <bits/std_function.h>	// std::function
 #endif
+#if __cplusplus >= 201402L
+# include <bits/predefined_ops.h> // std::_Not_fn
+#endif
 #if __cplusplus >= 201703L
 # if _GLIBCXX_HOSTED
 #  include <unordered_map>
@@ -1117,57 +1120,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif // __cpp_lib_bind_back
 
 #if __cplusplus >= 201402L
-  /// Generalized negator.
-  template<typename _Fn>
-    class _Not_fn
-    {
-      template<typename _Fn2, typename... _Args>
-	using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type;
-
-      template<typename _Tp>
-	static decltype(!std::declval<_Tp>())
-	_S_not() noexcept(noexcept(!std::declval<_Tp>()));
-
-    public:
-      template<typename _Fn2>
-	constexpr
-	_Not_fn(_Fn2&& __fn, int)
-	: _M_fn(std::forward<_Fn2>(__fn)) { }
-
-      _Not_fn(const _Not_fn& __fn) = default;
-      _Not_fn(_Not_fn&& __fn) = default;
-      ~_Not_fn() = default;
-
-      // Macro to define operator() with given cv-qualifiers ref-qualifiers,
-      // forwarding _M_fn and the function arguments with the same qualifiers,
-      // and deducing the return type and exception-specification.
-#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS )				\
-      template<typename... _Args,					\
-	       typename = enable_if_t<__is_invocable<_Fn _QUALS, _Args...>::value>> \
-	_GLIBCXX20_CONSTEXPR						\
-	decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())		\
-	operator()(_Args&&... __args) _QUALS				\
-	noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value	\
-	    && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()))	\
-	{								\
-	  return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn),	\
-				std::forward<_Args>(__args)...);	\
-	}								\
-									\
-      template<typename... _Args,					\
-	       typename = enable_if_t<!__is_invocable<_Fn _QUALS, _Args...>::value>> \
-	void operator()(_Args&&... __args) _QUALS = delete;
-
-      _GLIBCXX_NOT_FN_CALL_OP( & )
-      _GLIBCXX_NOT_FN_CALL_OP( const & )
-      _GLIBCXX_NOT_FN_CALL_OP( && )
-      _GLIBCXX_NOT_FN_CALL_OP( const && )
-#undef _GLIBCXX_NOT_FN_CALL_OP
-
-    private:
-      _Fn _M_fn;
-    };
-
   template<typename _Tp, typename _Pred>
     struct __is_byte_like : false_type { };
 
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 55144409cca..08c3280fa52 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -49,7 +49,7 @@
 #include <bits/stl_function.h> // For less
 #include <ext/numeric_traits.h>
 #include <bits/stl_algobase.h>
-#include <bits/refwrap.h>
+#include <bits/move.h>
 #include <bits/range_access.h>
 #include <bits/basic_string.h>
 #include <bits/basic_string.tcc>
@@ -95,11 +95,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
     erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
     {
-      using namespace __gnu_cxx;
       const auto __osz = __cont.size();
       const auto __end = __cont.end();
-      auto __removed = std::__remove_if(__cont.begin(), __end,
-					__ops::__pred_iter(std::ref(__pred)));
+      auto __removed = std::__remove_if
+	(__cont.begin(), __end, std::move(__pred));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
@@ -112,8 +111,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using namespace __gnu_cxx;
       const auto __osz = __cont.size();
       const auto __end = __cont.end();
-      auto __removed = std::__remove_if(__cont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+      auto __removed = std::__remove_if
+	(__cont.begin(), __end, __ops::__equal_val(__value));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index a1f7ef86824..b3add3a1d9e 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -65,7 +65,7 @@
 #include <bits/stl_uninitialized.h>
 #include <bits/stl_vector.h>
 #include <bits/stl_bvector.h>
-#include <bits/refwrap.h>
+#include <bits/move.h>
 #include <bits/range_access.h>
 
 #ifndef _GLIBCXX_EXPORT_TEMPLATE
@@ -112,12 +112,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename vector<_Tp, _Alloc>::size_type
     erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
     {
-      using namespace __gnu_cxx;
       _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __ucont = __cont;
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
-      auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__pred_iter(std::ref(__pred)));
+      auto __removed = std::__remove_if
+	(__ucont.begin(), __end, std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -137,8 +136,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __ucont = __cont;
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
-      auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+      auto __removed = std::__remove_if
+	(__ucont.begin(), __end, __ops::__equal_val(__value));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc
index f9958c690f8..86bae3e3d7c 100644
--- a/libstdc++-v3/src/c++17/memory_resource.cc
+++ b/libstdc++-v3/src/c++17/memory_resource.cc
@@ -26,6 +26,7 @@
 #include <algorithm>			// lower_bound, rotate
 #include <atomic>
 #include <bit>				// has_single_bit, bit_ceil, bit_width
+#include <functional>			// less_equal
 #include <new>
 #include <bits/move.h>			// std::__exchange
 #if ATOMIC_POINTER_LOCK_FREE != 2

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-06-05 16:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-05 16:56 [PATCH] Re-implement predefined operators François Dumont

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).