diff mbox series

Reimplement __gnu_cxx::__ops operators

Message ID 6b960f74-7ef7-8c3f-20bd-3f5a19d1f449@gmail.com
State New
Headers show
Series Reimplement __gnu_cxx::__ops operators | expand

Commit Message

François Dumont June 15, 2023, 5:07 a.m. UTC
I think we all agree that __gnu_cxx::__ops needed to be reimplemented, 
here it is.

Note that I kept the usage of std::ref in <string>, <vector> and <deque>.

     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
     predicates used in predicates-aware algos. Doing so we need far less
     functors. It impose that iterators are dereference at algo level and
     not in the functors anymore.

     libstdc++-v3/ChangeLog:

             * include/std/functional (_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.
             * include/std/string: Likewise.
             * include/std/vector: Likewise.

Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.

Ok to commit ?

François

Comments

François Dumont Dec. 6, 2023, 8:54 p.m. UTC | #1
I think I still got no feedback about this cleanup proposal.

Here is a new version.

François

On 15/06/2023 07:07, François Dumont wrote:
> I think we all agree that __gnu_cxx::__ops needed to be reimplemented, 
> here it is.
>
> Note that I kept the usage of std::ref in <string>, <vector> and <deque>.
>
>     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
>     predicates used in predicates-aware algos. Doing so we need far less
>     functors. It impose that iterators are dereference at algo level and
>     not in the functors anymore.
>
>     libstdc++-v3/ChangeLog:
>
>             * include/std/functional (_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.
>             * include/std/string: Likewise.
>             * include/std/vector: Likewise.
>
> Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
>
> Ok to commit ?
>
> François
>
diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h
index e9933373ed9..8753e6f64cd 100644
--- a/libstdc++-v3/include/bits/predefined_ops.h
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -32,376 +32,229 @@
 
 #include <bits/move.h>
 
+#if __cplusplus >= 201103L
+# include <bits/invoke.h>
+#endif
+
 namespace __gnu_cxx
 {
 namespace __ops
 {
-  struct _Iter_less_iter
+  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()(const _Lhs& __lhs, const _Rhs& __rhs) const
+      { return __lhs < __rhs; }
   };
 
   _GLIBCXX14_CONSTEXPR
-  inline _Iter_less_iter
-  __iter_less_iter()
-  { return _Iter_less_iter(); }
-
-  struct _Iter_less_val
-  {
-#if __cplusplus >= 201103L
-    constexpr _Iter_less_val() = default;
-#else
-    _Iter_less_val() { }
-#endif
-
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Iter_less_val(_Iter_less_iter) { }
-
-    template<typename _Iterator, typename _Value>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it < __val; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_less_val()
-  { return _Iter_less_val(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_comp_val(_Iter_less_iter)
-  { return _Iter_less_val(); }
-
-  struct _Val_less_iter
-  {
-#if __cplusplus >= 201103L
-    constexpr _Val_less_iter() = default;
-#else
-    _Val_less_iter() { }
-#endif
-
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Val_less_iter(_Iter_less_iter) { }
-
-    template<typename _Value, typename _Iterator>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Value& __val, _Iterator __it) const
-      { return __val < *__it; }
-  };
+  inline _Less
+  __less()
+  { return _Less(); }
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_less_iter()
-  { return _Val_less_iter(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_comp_iter(_Iter_less_iter)
-  { return _Val_less_iter(); }
-
-  struct _Iter_equal_to_iter
+  struct _Equal_to
   {
-    template<typename _Iterator1, typename _Iterator2>
+    template<typename _Lhs, typename _Rhs>
       _GLIBCXX20_CONSTEXPR
       bool
-      operator()(_Iterator1 __it1, _Iterator2 __it2) const
-      { return *__it1 == *__it2; }
+      operator()(const _Lhs& __lhs, const _Rhs& __rhs) const
+      { 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
-      bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it == __val; }
-  };
+  inline _Equal_to
+  __equal_to()
+  { return _Equal_to(); }
 
-  _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(); }
-
-  template<typename _Compare>
-    struct _Iter_comp_iter
+  template<typename _Val>
+    struct _Equal_to_val
     {
-      _Compare _M_comp;
-
-      explicit _GLIBCXX14_CONSTEXPR
-      _Iter_comp_iter(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
-
-      template<typename _Iterator1, typename _Iterator2>
-        _GLIBCXX14_CONSTEXPR
-        bool
-        operator()(_Iterator1 __it1, _Iterator2 __it2)
-        { return bool(_M_comp(*__it1, *__it2)); }
-    };
-
-  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
-    {
-      _Compare _M_comp;
+      const _Val& _M_val;
 
       _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
+      _Equal_to_val(const _Val& __val)
+      : _M_val(__val)
       { }
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
-	: _M_comp(__comp._M_comp)
-      { }
-
-#if __cplusplus >= 201103L
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
-	: _M_comp(std::move(__comp._M_comp))
-      { }
-#endif
-
-      template<typename _Iterator, typename _Value>
+      template<typename _Lhs>
 	_GLIBCXX20_CONSTEXPR
 	bool
-	operator()(_Iterator __it, _Value& __val)
-	{ return bool(_M_comp(*__it, __val)); }
+	operator()(const _Lhs& __lhs) const
+	{ return __lhs == _M_val; }
     };
 
-  template<typename _Compare>
+  template<typename _Val>
     _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_val<_Compare>
-    __iter_comp_val(_Compare __comp)
-    { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
+    inline _Equal_to_val<_Val>
+    __equal_to(const _Val& __val)
+    { return _Equal_to_val<_Val>(__val); }
 
-  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
+  template<typename _BinaryPred, typename _Val>
+    struct _Comp_val
     {
-      _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 _BPred>
+	constexpr
+	_Comp_val(_BPred&& __pred, const _Val& __val)
+	: _M_binary_pred(std::forward<_BPred>(__pred)), _M_val(__val)
+	{ }
+
+      _Comp_val(const _Comp_val&) = default;
+      _Comp_val(_Comp_val&&) = default;
+      ~_Comp_val() = default;
+#else
+    public:
+      _Comp_val(_BinaryPred __pred, const _Val& __val)
+      : _M_binary_pred(__pred), _M_val(__val)
       { }
 #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)); }
-
-  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)); }
-
-  template<typename _Value>
-    struct _Iter_equals_val
-    {
-      _Value& _M_value;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_val(_Value& __value)
-	: _M_value(__value)
-      { }
-
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return *__it == _M_value; }
-    };
-
-  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
-    {
-      _Iterator1 _M_it1;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_iter(_Iterator1 __it1)
-	: _M_it1(__it1)
-      { }
-
-      template<typename _Iterator2>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator2 __it2)
-	{ return *__it2 == *_M_it1; }
-    };
-
-  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
-    {
-      _Predicate _M_pred;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_pred(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
-      { }
-
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_pred(*__it)); }
-    };
-
-  template<typename _Predicate>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_pred<_Predicate>
-    __pred_iter(_Predicate __pred)
-    { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); }
-
-  template<typename _Compare, typename _Value>
-    struct _Iter_comp_to_val
-    {
-      _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 _Iterator>
-	_GLIBCXX20_CONSTEXPR
+#if __cplusplus >= 201103L
+      // 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, const _Val&>::value>> 	\
+	_GLIBCXX20_CONSTEXPR						\
+	bool								\
+	operator()(_Arg&& __arg) _QUALS					\
+	noexcept(std::__is_nothrow_invocable<				\
+		 _BinaryPred _QUALS, _Arg, const _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, const _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 _Lhs>
 	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_comp(*__it, _M_value)); }
+	operator()(const _Lhs& __lhs)
+	{ return bool(_M_binary_pred(__lhs, _M_val)); }
+#endif
+    private:
+      _BinaryPred _M_binary_pred;
+      const _Val& _M_val;
     };
 
-  template<typename _Compare, typename _Value>
-    _Iter_comp_to_val<_Compare, _Value>
+#if __cplusplus >= 201103L
+  template<typename _BPred, typename _Val>
     _GLIBCXX20_CONSTEXPR
-    __iter_comp_val(_Compare __comp, _Value &__val)
+    inline _Comp_val<std::__decay_t<_BPred>, _Val>
+    __comp_val(_BPred&& __pred, 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
+	_Comp_val<std::__decay_t<_BPred>, _Val>(std::forward<_BPred>(__pred),
+						__val);
     }
+#else
+  template<typename _BPred, typename _Val>
+    inline _Comp_val<_BPred, _Val>
+    __comp_val(_BPred __pred, const _Val& __val)
+    { return _Comp_val<_BPred, _Val>(__pred, __val); }
+#endif
+} // namespace __ops
+} // namespace __gnu_cxx
 
-  template<typename _Compare, typename _Iterator1>
-    struct _Iter_comp_to_iter
-    {
-      _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)); }
-    };
 
-  template<typename _Compare, typename _Iterator>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_to_iter<_Compare, _Iterator>
-    __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
-    {
-      return _Iter_comp_to_iter<_Compare, _Iterator>(
-	  _GLIBCXX_MOVE(__comp._M_comp), __it);
-    }
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  template<typename _Predicate>
-    struct _Iter_negate
+  /// Generalized negator.
+  template<typename _Fn>
+    class _Not_fn
     {
-      _Predicate _M_pred;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_negate(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
-      { }
+#if __cplusplus >= 201103L
+      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;
+#else
+    public:
+      _Not_fn(_Fn __fn, int)
+      : _M_fn(__fn) { }
+#endif
 
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
+#if __cplusplus >= 201103L
+      // 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
+      template<typename _Arg>
 	bool
-	operator()(_Iterator __it)
-	{ return !bool(_M_pred(*__it)); }
+	operator()(const _Arg& __arg)
+	{ return !bool(_M_fn(__arg)); }
+#endif
+    private:
+      _Fn _M_fn;
     };
 
-  template<typename _Predicate>
+#if __cplusplus >= 201103L
+  template<typename _Fn>
     _GLIBCXX20_CONSTEXPR
-    inline _Iter_negate<_Predicate>
-    __negate(_Iter_pred<_Predicate> __pred)
-    { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); }
+    inline _Not_fn<std::__decay_t<_Fn>>
+    __not_fn(_Fn&& __fn)
+    noexcept(std::is_nothrow_constructible<std::__decay_t<_Fn>, _Fn&&>::value)
+    { return _Not_fn<std::__decay_t<_Fn>>{std::forward<_Fn>(__fn), 0}; }
+#else
+  template<typename _Fn>
+    inline _Not_fn<_Fn>
+    __not_fn(_Fn __fn)
+    { return _Not_fn<_Fn>(__fn, 0); }
+#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 0b34a4f86b0..2ef5b6717bd 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -85,18 +85,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
 			   _Iterator __c, _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);
@@ -110,7 +110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		  _Predicate __pred)
     {
       return std::__find_if(__first, __last,
-			    __gnu_cxx::__ops::__negate(__pred),
+			    std::__not_fn(_GLIBCXX_MOVE(__pred)),
 			    std::__iterator_category(__first));
     }
 
@@ -123,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
     {
       for (; __len; --__len,  (void) ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  break;
       return __first;
     }
@@ -160,7 +160,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;
@@ -199,7 +199,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
@@ -337,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::__find_end(__first1, __last1, __first2, __last2,
 			     std::__iterator_category(__first1),
 			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+			     __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -388,7 +388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::__find_end(__first1, __last1, __first2, __last2,
 			     std::__iterator_category(__first1),
 			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_comp_iter(__comp));
+			     _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -408,7 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +426,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +448,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +471,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 +494,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,7 +541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       return __first;
     }
-#endif
+#endif // C++11
 
   template<typename _InputIterator, typename _OutputIterator,
 	   typename _Predicate>
@@ -549,7 +551,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		     _OutputIterator __result, _Predicate __pred)
     {
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = *__first;
 	    ++__result;
@@ -586,7 +588,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__remove_copy_if(__first, __last, __result,
-	__gnu_cxx::__ops::__iter_equals_val(__value));
+				   __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -620,7 +622,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
@@ -796,7 +798,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__remove_if(__first, __last,
-		__gnu_cxx::__ops::__iter_equals_val(__value));
+			      __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -829,8 +831,7 @@ _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>
@@ -844,7 +845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _ForwardIterator __next = __first;
       while (++__next != __last)
 	{
-	  if (__binary_pred(__first, __next))
+	  if (__binary_pred(*__first, *__next))
 	    return __first;
 	  __first = __next;
 	}
@@ -866,7 +867,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;
     }
@@ -898,7 +899,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__unique(__first, __last,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+			   __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -930,8 +931,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));
     }
 
   /**
@@ -956,7 +956,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;
@@ -984,12 +984,9 @@ _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;
       while (++__first != __last)
-	if (!__rebound_pred(__first, __value))
+	if (!__binary_pred(*__first, __value))
 	  {
 	    __value = *__first;
 	    *++__result = __value;
@@ -1017,7 +1014,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;
     }
@@ -1479,7 +1476,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  ++__result2;
 	  ++__first;
 	  for (; __first != __last; ++__first)
-	    if (__pred(__first))
+	    if (__pred(*__first))
 	      {
 		*__result1 = _GLIBCXX_MOVE(*__first);
 		++__result1;
@@ -1534,7 +1531,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _Temporary_buffer<_ForwardIterator, _ValueType>
 	__buf(__first, std::distance(__first, __last));
       return
-	std::__stable_partition_adaptive(__first, __last, __pred,
+	std::__stable_partition_adaptive(__first, __last, _GLIBCXX_MOVE(__pred),
 					 _DistanceType(__buf.requested_size()),
 					 __buf.begin(),
 					 _DistanceType(__buf.size()));
@@ -1569,8 +1566,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
 
@@ -1586,7 +1582,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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);
     }
 
@@ -1619,14 +1615,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_MOVE(__comp));
       return __result_real_last;
     }
 
@@ -1677,7 +1674,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       return std::__partial_sort_copy(__first, __last,
 				      __result_first, __result_last,
-				      __gnu_cxx::__ops::__iter_less_iter());
+				      __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -1732,7 +1729,7 @@ _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
@@ -1748,7 +1745,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	__val = _GLIBCXX_MOVE(*__last);
       _RandomAccessIterator __next = __last;
       --__next;
-      while (__comp(__val, __next))
+      while (__comp(__val, *__next))
 	{
 	  *__last = _GLIBCXX_MOVE(*__next);
 	  __last = __next;
@@ -1764,11 +1761,12 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __insertion_sort(_RandomAccessIterator __first,
 		     _RandomAccessIterator __last, _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);
@@ -1776,8 +1774,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	      *__first = _GLIBCXX_MOVE(__val);
 	    }
 	  else
-	    std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	    std::__unguarded_linear_insert(__i, __comp);
 	}
     }
 
@@ -1789,8 +1786,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 			       _RandomAccessIterator __last, _Compare __comp)
     {
       for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
-	std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	std::__unguarded_linear_insert(__i, __comp);
     }
 
   /**
@@ -1810,10 +1806,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
 	  std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
-					  __comp);
+					  _GLIBCXX_MOVE(__comp));
 	}
       else
-	std::__insertion_sort(__first, __last, __comp);
+	std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function...
@@ -1826,10 +1822,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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;
@@ -1848,7 +1844,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _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);
+      return std::__unguarded_partition(__first + 1, __last, __first,
+					_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
@@ -1860,7 +1857,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 		   _Compare __comp)
     {
       std::__heap_select(__first, __middle, __last, __comp);
-      std::__sort_heap(__first, __middle, __comp);
+      std::__sort_heap(__first, __middle, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function for the sort routine.
@@ -1899,7 +1896,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  std::__introsort_loop(__first, __last,
 				std::__lg(__last - __first) * 2,
 				__comp);
-	  std::__final_insertion_sort(__first, __last, __comp);
+	  std::__final_insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
 	}
     }
 
@@ -1927,7 +1924,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  else
 	    __last = __cut;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   /// @endcond
@@ -1964,8 +1961,7 @@ _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>
@@ -1984,7 +1980,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
 	    {
@@ -2020,7 +2016,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
 
       return std::__upper_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__val_less_iter());
+				__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2051,17 +2047,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, _Comp __comp)
     {
       typedef typename iterator_traits<_ForwardIterator>::difference_type
 	_DistanceType;
@@ -2073,21 +2066,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_MOVE(__comp));
 	      return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
 	    }
 	}
@@ -2127,8 +2121,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __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());
+				__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2165,9 +2158,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));
     }
 
   /**
@@ -2197,7 +2188,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       _ForwardIterator __i
 	= std::__lower_bound(__first, __last, __val,
-			     __gnu_cxx::__ops::__iter_less_val());
+			     __gnu_cxx::__ops::__less());
       return __i != __last && !(__val < *__i);
     }
 
@@ -2232,8 +2223,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));
     }
 
@@ -2249,7 +2239,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2288,7 +2278,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,13 +2350,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
 	  std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
-				     __first, __comp);
+				     __first, _GLIBCXX_MOVE(__comp));
 	}
       else
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
 	  std::__move_merge_adaptive_backward(__first, __middle, __buffer,
-					      __buffer_end, __last, __comp);
+					      __buffer_end, __last,
+					      _GLIBCXX_MOVE(__comp));
 	}
     }
 
@@ -2382,7 +2373,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       if (__len1 <= __buffer_size || __len2 <= __buffer_size)
 	std::__merge_adaptive(__first, __middle, __last,
-			      __len1, __len2, __buffer, __comp);
+			      __len1, __len2, __buffer, _GLIBCXX_MOVE(__comp));
       else
 	{
 	  _BidirectionalIterator __first_cut = __first;
@@ -2394,8 +2385,7 @@ _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));
+		= std::__lower_bound(__middle, __last, *__first_cut, __comp);
 	      __len22 = std::distance(__middle, __second_cut);
 	    }
 	  else
@@ -2403,8 +2393,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	      __len22 = __len2 / 2;
 	      std::advance(__second_cut, __len22);
 	      __first_cut
-		= std::__upper_bound(__first, __middle, *__second_cut,
-				     __gnu_cxx::__ops::__val_comp_iter(__comp));
+		= std::__upper_bound(__first, __middle, *__second_cut, __comp);
 	      __len11 = std::distance(__first, __first_cut);
 	    }
 
@@ -2418,7 +2407,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_MOVE(__comp));
 	}
     }
 
@@ -2437,7 +2427,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       if (__len1 + __len2 == 2)
 	{
-	  if (__comp(__middle, __first))
+	  if (__comp(*__middle, *__first))
 	    std::iter_swap(__first, __middle);
 	  return;
 	}
@@ -2451,8 +2441,7 @@ _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));
+	    = std::__lower_bound(__middle, __last, *__first_cut, __comp);
 	  __len22 = std::distance(__middle, __second_cut);
 	}
       else
@@ -2460,8 +2449,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  __len22 = __len2 / 2;
 	  std::advance(__second_cut, __len22);
 	  __first_cut
-	    = std::__upper_bound(__first, __middle, *__second_cut,
-				 __gnu_cxx::__ops::__val_comp_iter(__comp));
+	    = std::__upper_bound(__first, __middle, *__second_cut, __comp);
 	  __len11 = std::distance(__first, __first_cut);
 	}
 
@@ -2470,7 +2458,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_MOVE(__comp));
     }
 
   template<typename _BidirectionalIterator, typename _Compare>
@@ -2498,18 +2487,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _TmpBuf __buf(__first, std::min(__len1, __len2));
 
       if (__builtin_expect(__buf.size() == __buf.requested_size(), true))
-	std::__merge_adaptive
-	  (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp);
+	std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
+			      __buf.begin(), _GLIBCXX_MOVE(__comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
-	std::__merge_without_buffer
-	  (__first, __middle, __last, __len1, __len2, __comp);
+	std::__merge_without_buffer(__first, __middle, __last, __len1, __len2,
+				    _GLIBCXX_MOVE(__comp));
       else
-	std::__merge_adaptive_resize
-	  (__first, __middle, __last, __len1, __len2, __buf.begin(),
-	   _DistanceType(__buf.size()), __comp);
+	std::__merge_adaptive_resize(__first, __middle, __last, __len1, __len2,
+				     __buf.begin(), _DistanceType(__buf.size()),
+				     _GLIBCXX_MOVE(__comp));
 #else
       std::__merge_without_buffer
-	(__first, __middle, __last, __len1, __len2, __comp);
+	(__first, __middle, __last, __len1, __len2, _GLIBCXX_MOVE(__comp));
 #endif
     }
 
@@ -2547,7 +2536,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       std::__inplace_merge(__first, __middle, __last,
-			   __gnu_cxx::__ops::__iter_less_iter());
+			   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2589,8 +2578,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));
     }
 
 
@@ -2604,7 +2592,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2617,8 +2605,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,
@@ -2642,7 +2629,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_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Distance,
@@ -2658,7 +2646,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  std::__insertion_sort(__first, __first + __chunk_size, __comp);
 	  __first += __chunk_size;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   enum { _S_chunk_size = 7 };
@@ -2724,11 +2712,11 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 				       _Distance(__middle - __first),
 				       _Distance(__last - __middle),
 				       __buffer, __buffer_size,
-				       __comp);
+				       _GLIBCXX_MOVE(__comp));
 	}
       else
 	std::__stable_sort_adaptive(__first, __middle, __last,
-				    __buffer, __comp);
+				    __buffer, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function for the stable sorting routines.
@@ -2748,7 +2736,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       std::__merge_without_buffer(__first, __middle, __last,
 				  __middle - __first,
 				  __last - __middle,
-				  __comp);
+				  _GLIBCXX_MOVE(__comp));
     }
 
   // stable_sort
@@ -2768,9 +2756,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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;
 	}
@@ -2817,7 +2805,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return std::__includes(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_less_iter());
+			     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2864,7 +2852,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
@@ -2896,10 +2884,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,
@@ -2942,7 +2930,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__next_permutation
-	(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+	(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2975,8 +2963,7 @@ _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>
@@ -2998,10 +2985,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,
@@ -3045,7 +3032,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__prev_permutation(__first, __last,
-				     __gnu_cxx::__ops::__iter_less_iter());
+				     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3078,8 +3065,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
@@ -3094,7 +3080,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 		      _Predicate __pred, const _Tp& __new_value)
     {
       for (; __first != __last; ++__first, (void)++__result)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  *__result = __new_value;
 	else
 	  *__result = *__first;
@@ -3131,8 +3117,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__replace_copy_if(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_equals_val(__old_value),
-					      __new_value);
+				    __gnu_cxx::__ops::__equal_to(__old_value),
+				    __new_value);
     }
 
   /**
@@ -3167,8 +3153,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
@@ -3199,7 +3184,9 @@ _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
@@ -3212,7 +3199,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       _ForwardIterator __next = __first;
       for (++__next; __next != __last; __first = __next, (void)++__next)
-	if (__comp(__next, __first))
+	if (__comp(*__next, *__first))
 	  return __next;
       return __next;
     }
@@ -3238,7 +3225,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());
     }
 
   /**
@@ -3264,8 +3251,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));
     }
 
   /**
@@ -3318,7 +3304,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;
@@ -3337,25 +3323,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;
 	    }
 
@@ -3389,8 +3375,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return std::__minmax_element(__first, __last,
-				   __gnu_cxx::__ops::__iter_less_iter());
+      return std::__minmax_element(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3419,8 +3404,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>
@@ -3431,7 +3415,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);
     }
 
@@ -3442,8 +3426,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);
     }
 
@@ -3477,7 +3460,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
@@ -3508,7 +3491,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)
@@ -3529,14 +3512,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::__comp_val(__pred, *__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::__comp_val(__pred, *__scan));
 	  if (0 == __matches
 	      || std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+			__gnu_cxx::__ops::__comp_val(__pred, *__scan))
 	      != __matches)
 	    return false;
 	}
@@ -3567,7 +3550,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());
     }
 
   /**
@@ -3596,7 +3579,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
 
@@ -3841,7 +3824,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		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));
+			    __gnu_cxx::__ops::__equal_to(__val));
     }
 
   /**
@@ -3866,8 +3849,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));
     }
 
   /**
@@ -3972,7 +3954,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__adjacent_find(__first, __last,
-				  __gnu_cxx::__ops::__iter_equal_to_iter());
+				  __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -4000,7 +3982,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));
     }
 
   /**
@@ -4024,7 +4006,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__count_if(__first, __last,
-			     __gnu_cxx::__ops::__iter_equals_val(__value));
+			     __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -4047,8 +4029,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));
     }
 
   /**
@@ -4093,7 +4074,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__search(__first1, __last1, __first2, __last2,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+			   __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -4124,7 +4105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__search_n(__first, __last, __count,
-			     __gnu_cxx::__ops::__iter_equals_val(__val));
+			     __gnu_cxx::__ops::__equal_to(__val));
     }
 
 
@@ -4160,7 +4141,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__search_n(__first, __last, __count,
-		__gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
+	__gnu_cxx::__ops::__comp_val(_GLIBCXX_MOVE(__binary_pred), __val));
     }
 
 #if __cplusplus >= 201703L
@@ -4417,7 +4398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last)
 	return __result;
       return std::__unique_copy(__first, __last, __result,
-				__gnu_cxx::__ops::__iter_equal_to_iter(),
+				__gnu_cxx::__ops::__equal_to(),
 				std::__iterator_category(__first),
 				std::__iterator_category(__result));
     }
@@ -4457,7 +4438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last)
 	return __result;
       return std::__unique_copy(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
+				_GLIBCXX_MOVE(__binary_pred),
 				std::__iterator_category(__first),
 				std::__iterator_category(__result));
     }
@@ -4573,7 +4554,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));
     }
 
@@ -4612,7 +4593,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       std::__partial_sort(__first, __middle, __last,
-			  __gnu_cxx::__ops::__iter_less_iter());
+			  __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4652,8 +4633,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));
     }
 
   /**
@@ -4691,7 +4671,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       std::__introselect(__first, __nth, __last,
 			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_less_iter());
+			 __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4732,7 +4712,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       std::__introselect(__first, __nth, __last,
 			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_comp_iter(__comp));
+			 _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -4762,7 +4742,7 @@ _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());
+      std::__sort(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4795,7 +4775,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,
@@ -4808,7 +4788,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = *__first2;
 	      ++__first2;
@@ -4868,7 +4848,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__merge(__first1, __last1,
 				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+				     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4918,8 +4898,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
       return _GLIBCXX_STD_A::__merge(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				     __first2, __last2, __result,
+				     _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
@@ -4944,14 +4924,16 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__builtin_expect(__buf.requested_size() == __buf.size(), true))
 	std::__stable_sort_adaptive(__first,
 				    __first + _DistanceType(__buf.size()),
-				    __last, __buf.begin(), __comp);
+				    __last, __buf.begin(),
+				    _GLIBCXX_MOVE(__comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
-	std::__inplace_stable_sort(__first, __last, __comp);
+	std::__inplace_stable_sort(__first, __last, _GLIBCXX_MOVE(__comp));
       else
 	std::__stable_sort_adaptive_resize(__first, __last, __buf.begin(),
-					   _DistanceType(__buf.size()), __comp);
+					   _DistanceType(__buf.size()),
+					   _GLIBCXX_MOVE(__comp));
 #else
-      std::__inplace_stable_sort(__first, __last, __comp);
+      std::__inplace_stable_sort(__first, __last, _GLIBCXX_MOVE(__comp));
 #endif
     }
 
@@ -4985,7 +4967,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_less_iter());
+				    __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5021,7 +5003,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_comp_iter(__comp));
+				    _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5035,12 +5017,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       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;
@@ -5103,8 +5085,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_union(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_less_iter());
+					 __first2, __last2, __result,
+					 __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5154,8 +5136,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+					 __first2, __last2, __result,
+					 _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5168,9 +5150,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		       _OutputIterator __result, _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
 	  {
@@ -5225,8 +5207,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
-				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+						__first2, __last2, __result,
+						__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5275,8 +5257,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+						__first2, __last2, __result,
+						_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5289,13 +5271,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		     _OutputIterator __result, _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
 	  {
@@ -5350,8 +5332,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
-				   __first2, __last2, __result,
-				   __gnu_cxx::__ops::__iter_less_iter());
+					      __first2, __last2, __result,
+					      __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5402,8 +5384,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+					      __first2, __last2, __result,
+					      _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5419,13 +5401,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 			       _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;
@@ -5486,7 +5468,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
 					__first2, __last2, __result,
-					__gnu_cxx::__ops::__iter_less_iter());
+					__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5539,7 +5521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
 				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
@@ -5552,7 +5534,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__first, __result))
+	if (__comp(*__first, *__result))
 	  __result = __first;
       return __result;
     }
@@ -5577,7 +5559,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+					   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5604,7 +5586,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+					   _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
@@ -5616,7 +5598,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last) return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__result, __first))
+	if (__comp(*__result, *__first))
 	  __result = __first;
       return __result;
     }
@@ -5641,7 +5623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+					   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5668,7 +5650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+					   _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -5680,7 +5662,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>
@@ -5690,7 +5672,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>
@@ -5700,7 +5682,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>
@@ -5710,7 +5692,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 6276d85b86f..bf404bf849b 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1300,9 +1300,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;
@@ -1316,10 +1316,9 @@ _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());
+						__gnu_cxx::__ops::__less());
 	}
 
       template<typename _II1, typename _II2>
@@ -1469,7 +1468,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;
@@ -1505,7 +1504,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
 
       return std::__lower_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_less_val());
+				__gnu_cxx::__ops::__less());
     }
 
   /// This is a helper function for the sort routines and for random.tcc.
@@ -1634,7 +1633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	  if (__d1 != __d2)
 	    return false;
 	  return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
-				       __binary_pred);
+				       std::move(__binary_pred));
 	}
 
       for (; __first1 != __last1 && __first2 != __last2;
@@ -1772,8 +1771,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
@@ -1878,7 +1876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
 	       _InputIterator2 __first2, _BinaryPredicate __binary_pred)
     {
-      while (__first1 != __last1 && __binary_pred(__first1, __first2))
+      while (__first1 != __last1 && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -1914,7 +1912,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+					__gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -1946,7 +1944,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
@@ -1959,7 +1957,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	       _BinaryPredicate __binary_pred)
     {
       while (__first1 != __last1 && __first2 != __last2
-	     && __binary_pred(__first1, __first2))
+	     && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -1997,7 +1995,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+					__gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -2032,7 +2030,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
 
@@ -2045,7 +2043,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
     __find_if(_InputIterator __first, _InputIterator __last,
 	      _Predicate __pred, input_iterator_tag)
     {
-      while (__first != __last && !__pred(__first))
+      while (__first != __last && !__pred(*__first))
 	++__first;
       return __first;
     }
@@ -2062,19 +2060,19 @@ _GLIBCXX_END_NAMESPACE_ALGO
 
       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;
 	}
@@ -2082,17 +2080,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
@@ -2118,7 +2116,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
     {
       typename iterator_traits<_InputIterator>::difference_type __n = 0;
       for (; __first != __last; ++__first)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  ++__n;
       return __n;
     }
@@ -2135,7 +2133,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
       _ForwardIterator __result = __first;
       ++__first;
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = _GLIBCXX_MOVE(*__first);
 	    ++__result;
@@ -2149,7 +2147,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
     _ForwardIterator1
     __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
 	     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	     _BinaryPredicate  __predicate)
+	     _BinaryPredicate  __pred)
     {
       // Test for empty ranges
       if (__first1 == __last1 || __first2 == __last2)
@@ -2159,7 +2157,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
       _ForwardIterator2 __p1(__first2);
       if (++__p1 == __last2)
 	return std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+	  __gnu_cxx::__ops::__comp_val(_GLIBCXX_MOVE(__pred), *__first2));
 
       // General case.
       _ForwardIterator1 __current = __first1;
@@ -2168,7 +2166,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
 	{
 	  __first1 =
 	    std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+			   __gnu_cxx::__ops::__comp_val(__pred, *__first2));
 
 	  if (__first1 == __last1)
 	    return __last1;
@@ -2178,7 +2176,7 @@ _GLIBCXX_END_NAMESPACE_ALGO
 	  if (++__current == __last1)
 	    return __last1;
 
-	  while (__predicate(__current, __p))
+	  while (__pred(*__current, *__p))
 	    {
 	      if (++__p == __last2)
 		return __first1;
@@ -2201,7 +2199,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)
@@ -2214,15 +2212,15 @@ _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::__comp_val(__pred, *__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::__comp_val(__pred, *__scan));
 	  if (0 == __matches ||
 	      std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+			      __gnu_cxx::__ops::__comp_val(__pred, *__scan))
 	      != __matches)
 	    return false;
 	}
@@ -2256,7 +2254,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
 
@@ -2301,7 +2299,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 551c3687624..854d1cffd67 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)
+		    _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,8 +94,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline bool
     __is_heap(_RandomAccessIterator __first, _Distance __n)
     {
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      return std::__is_heap_until(__first, __n, __comp) == __n;
+      return std::__is_heap_until(__first, __n,
+				  __gnu_cxx::__ops::__less()) == __n;
     }
 
   template<typename _RandomAccessIterator, typename _Compare,
@@ -104,9 +104,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline bool
     __is_heap(_RandomAccessIterator __first, _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_MOVE(__comp)) == __n;
     }
 
   template<typename _RandomAccessIterator>
@@ -134,10 +133,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     __push_heap(_RandomAccessIterator __first,
 		_Distance __holeIndex, _Distance __topIndex, _Tp __value,
-		_Compare& __comp)
+		_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;
@@ -174,10 +173,10 @@ _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));
       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
-		       _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
+		       _DistanceType(0), _GLIBCXX_MOVE(__value),
+		       __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -210,11 +209,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,
@@ -229,8 +227,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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 +240,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 						     + (__secondChild - 1)));
 	  __holeIndex = __secondChild - 1;
 	}
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
-	__cmp(_GLIBCXX_MOVE(__comp));
       std::__push_heap(__first, __holeIndex, __topIndex,
-		       _GLIBCXX_MOVE(__value), __cmp);
+		       _GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     inline void
     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	       _RandomAccessIterator __result, _Compare& __comp)
+	       _RandomAccessIterator __result, _Compare __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	_ValueType;
@@ -263,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       *__result = _GLIBCXX_MOVE(*__first);
       std::__adjust_heap(__first, _DistanceType(0),
 			 _DistanceType(__last - __first),
-			 _GLIBCXX_MOVE(__value), __comp);
+			 _GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -295,8 +291,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__last - __first > 1)
 	{
 	  --__last;
-	  __gnu_cxx::__ops::_Iter_less_iter __comp;
-	  std::__pop_heap(__first, __last, __last, __comp);
+	  std::__pop_heap(__first, __last, __last,
+			  __gnu_cxx::__ops::__less());
 	}
     }
 
@@ -327,10 +323,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 +332,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		_Compare& __comp)
+		_Compare __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	  _ValueType;
@@ -382,8 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      std::__make_heap(__first, __last, __comp);
+      std::__make_heap(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -408,16 +401,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)
+		_Compare __comp)
     {
       while (__last - __first > 1)
 	{
@@ -448,8 +439,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive(__first, __last);
       __glibcxx_requires_heap(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      std::__sort_heap(__first, __last, __comp);
+      std::__sort_heap(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -475,9 +465,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 +492,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 +520,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),
+			       _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -572,9 +559,8 @@ _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,
+				  _GLIBCXX_MOVE(__comp)) == __dist;
     }
 #endif
 
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index e48dc9968e8..ebca63dc1da 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)));
+					std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -124,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__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 729d11c9804..2d8b806fa0d 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>
@@ -1039,57 +1042,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif // __cpp_lib_bind_front
 
 #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 78e8bacc007..af2a7ef8ca1 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)));
+					std::move(__pred));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
@@ -113,7 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __cont.end();
       auto __removed = std::__remove_if(__cont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__value));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 5e1d54a04ac..2dfc7b4798e 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)));
+					std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -138,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__value));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
Jonathan Wakely Dec. 7, 2023, 1:41 p.m. UTC | #2
On Wed, 6 Dec 2023 at 20:55, François Dumont <frs.dumont@gmail.com> wrote:
>
> I think I still got no feedback about this cleanup proposal.

Can you remind me why we have all those different functions in
predefined_ops.h in the first place? I think it was to avoid having
two versions of every algorithm, one that does *l < *r and one that
does pred(*l, *r), right?

One property of the current code is that _Iter_less_iter will compare
exactly *lhs < *rhs and so works even with this type, where its
operator< only accepts non-const arguments:

struct X { bool operator<(X&); };

Doesn't your simplification break that, because the _Less function
only accepts const references now?

Maybe another way to remove the number of types in predefined_ops.h
would be to compose functions from projections. So instead of
_Iter_less_iter and _Iter_less_val etc. we have:

template<typename LProj, typename RProj>
struct _Less
{
  template<typename T, typename U>
    bool operator()(T& l, U& r) const
    { return LProj()(l) < RProj()(r); }
};

And a set of projections:

struct _Proj_deref {
  template<typename T>
    decltype(auto) operator()(T& t) const
    { return *t; }
};
struct _Proj_identity {
  template<typename T>
    T& operator()(T& t) const
    { return t; }
};

Then:

using _Iter_less_iter =_Less<_Proj_deref, _Proj_deref>;
using _Iter_less_val = _Less<_Proj_deref, _Proj_identity>;

The problem here is the use of decltype(auto) which isn't valid in
C++98. If we didn't have to support C++98 then we could just use
forwarding refs in_Less::operator()(T&&, U&&) and use perfect
forwarding everywhere. But we can't.


>
> Here is a new version.
>
> François
>
> On 15/06/2023 07:07, François Dumont wrote:
> > I think we all agree that __gnu_cxx::__ops needed to be reimplemented,
> > here it is.
> >
> > Note that I kept the usage of std::ref in <string>, <vector> and <deque>.
> >
> >     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
> >     predicates used in predicates-aware algos. Doing so we need far less
> >     functors. It impose that iterators are dereference at algo level and
> >     not in the functors anymore.
> >
> >     libstdc++-v3/ChangeLog:
> >
> >             * include/std/functional (_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.
> >             * include/std/string: Likewise.
> >             * include/std/vector: Likewise.
> >
> > Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
> >
> > Ok to commit ?
> >
> > François
> >
Jonathan Wakely Dec. 7, 2023, 2:04 p.m. UTC | #3
On Thu, 7 Dec 2023 at 13:41, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Wed, 6 Dec 2023 at 20:55, François Dumont <frs.dumont@gmail.com> wrote:
> >
> > I think I still got no feedback about this cleanup proposal.
>
> Can you remind me why we have all those different functions in
> predefined_ops.h in the first place? I think it was to avoid having
> two versions of every algorithm, one that does *l < *r and one that
> does pred(*l, *r), right?
>
> One property of the current code is that _Iter_less_iter will compare
> exactly *lhs < *rhs and so works even with this type, where its
> operator< only accepts non-const arguments:
>
> struct X { bool operator<(X&); };
>
> Doesn't your simplification break that, because the _Less function
> only accepts const references now?
>
> Maybe another way to remove the number of types in predefined_ops.h
> would be to compose functions from projections. So instead of
> _Iter_less_iter and _Iter_less_val etc. we have:
>
> template<typename LProj, typename RProj>
> struct _Less
> {
>   template<typename T, typename U>
>     bool operator()(T& l, U& r) const
>     { return LProj()(l) < RProj()(r); }
> };
>
> And a set of projections:
>
> struct _Proj_deref {
>   template<typename T>
>     decltype(auto) operator()(T& t) const
>     { return *t; }
> };
> struct _Proj_identity {
>   template<typename T>
>     T& operator()(T& t) const
>     { return t; }
> };
>
> Then:
>
> using _Iter_less_iter =_Less<_Proj_deref, _Proj_deref>;
> using _Iter_less_val = _Less<_Proj_deref, _Proj_identity>;
>
> The problem here is the use of decltype(auto) which isn't valid in
> C++98. If we didn't have to support C++98 then we could just use
> forwarding refs in_Less::operator()(T&&, U&&) and use perfect
> forwarding everywhere. But we can't.

I suppose we could use typename iterator_traits<T>::reference instead
of decltype(auto), and hope that typedef is actuallyaccurate, and what
dereferencing the iterator gives us.

I do like the idea of simplifying the algos this way, I'm just
concerned that the changes to the ops will break some code that works
today.


>
>
> >
> > Here is a new version.
> >
> > François
> >
> > On 15/06/2023 07:07, François Dumont wrote:
> > > I think we all agree that __gnu_cxx::__ops needed to be reimplemented,
> > > here it is.
> > >
> > > Note that I kept the usage of std::ref in <string>, <vector> and <deque>.
> > >
> > >     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
> > >     predicates used in predicates-aware algos. Doing so we need far less
> > >     functors. It impose that iterators are dereference at algo level and
> > >     not in the functors anymore.
> > >
> > >     libstdc++-v3/ChangeLog:
> > >
> > >             * include/std/functional (_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.
> > >             * include/std/string: Likewise.
> > >             * include/std/vector: Likewise.
> > >
> > > Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.
> > >
> > > Ok to commit ?
> > >
> > > François
> > >
François Dumont Dec. 9, 2023, 1:04 p.m. UTC | #4
On 07/12/2023 14:41, Jonathan Wakely wrote:
> On Wed, 6 Dec 2023 at 20:55, François Dumont <frs.dumont@gmail.com> wrote:
>> I think I still got no feedback about this cleanup proposal.
> Can you remind me why we have all those different functions in
> predefined_ops.h in the first place? I think it was to avoid having
> two versions of every algorithm, one that does *l < *r and one that
> does pred(*l, *r), right?
Yes, that was the purpose.
>
> One property of the current code is that _Iter_less_iter will compare
> exactly *lhs < *rhs and so works even with this type, where its
> operator< only accepts non-const arguments:
>
> struct X { bool operator<(X&); };
>
> Doesn't your simplification break that, because the _Less function
> only accepts const references now?

Indeed, I thought more about the problem of const qualification on the 
operator(). This is why _Comp_val is mimicking what _Not_fn does.

To be honnest I even thought that this kind of operator above was more a 
user code issue than a real use case we need to handle. But it looks 
like you, I guess the C++ Standard then, impose to support it.

I'll rework it then, thanks for the proposal below and in your other email.
François Dumont April 4, 2024, 5:24 p.m. UTC | #5
On 07/12/2023 15:04, Jonathan Wakely wrote:
> On Thu, 7 Dec 2023 at 13:41, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On Wed, 6 Dec 2023 at 20:55, François Dumont <frs.dumont@gmail.com> wrote:
>>> I think I still got no feedback about this cleanup proposal.
>> Can you remind me why we have all those different functions in
>> predefined_ops.h in the first place? I think it was to avoid having
>> two versions of every algorithm, one that does *l < *r and one that
>> does pred(*l, *r), right?

Right !

>>
>> One property of the current code is that _Iter_less_iter will compare
>> exactly *lhs < *rhs and so works even with this type, where its
>> operator< only accepts non-const arguments:
>>
>> struct X { bool operator<(X&); };
>>
>> Doesn't your simplification break that, because the _Less function
>> only accepts const references now?

Yes, I thought it was ok to force users to do the right thing, make 
operators const-qualified and use mutable when they want to do fancy things.

But you think otherwise so here is another version more user-friendly.

In addition to simplifying, I think, predefined-ops it also implements 
perfect-forwarding of user functors. Some algos in stl_heap.h were 
already taking functor by ref.

I wanted to show it to you now because thanks to this patch I have an 
interesting failure that I cannot really explain. I just guess that the 
new version allow more inline-ment and triggers this:

In member function 'void std::__new_allocator<_Tp>::deallocate(_Tp*, 
size_type) [with _Tp = int]',
     inlined from 'constexpr void std::allocator< 
<template-parameter-1-1> >::deallocate(_Tp*, std::size_t) [with _Tp = 
int]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/allocator
.h:208,
     inlined from 'static constexpr void 
std::allocator_traits<std::allocator<_CharT> 
 >::deallocate(allocator_type&, pointer, size_type) [with _Tp = int]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstd
c++-v3/include/bits/alloc_traits.h:513,
     inlined from 'constexpr void std::_Vector_base<_Tp, 
_Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = 
std::allocator<int>]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v
3/include/bits/stl_vector.h:389,
     inlined from 'constexpr void std::_Vector_base<_Tp, 
_Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = 
std::allocator<int>]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v
3/include/bits/stl_vector.h:385,
     inlined from 'constexpr std::_Vector_base<_Tp, 
_Alloc>::~_Vector_base() [with _Tp = int; _Alloc = std::allocator<int>]' 
at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_vector
.h:368,
     inlined from 'constexpr std::vector<_Tp, _Alloc>::~vector() [with 
_Tp = int; _Alloc = std::allocator<int>]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_vector.h:738,
     inlined from 'void test01()' at 
/home/fdumont/dev/gcc/git/libstdc++-v3/testsuite/25_algorithms/merge/constrained.cc:52:
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/new_allocator.h:172: 
warning: 'void operator delete(void*, std::size_t)' called on pointer 
'<unknown>' with nonzero offset [4, 20] [-Wfre
e-nonheap-object]
In member function '_Tp* std::__new_allocator<_Tp>::allocate(size_type, 
const void*) [with _Tp = int]',
     inlined from 'constexpr _Tp* std::allocator< 
<template-parameter-1-1> >::allocate(std::size_t) [with _Tp = int]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/allocator.h:196,
     inlined from 'static constexpr _Tp* 
std::allocator_traits<std::allocator<_CharT> 
 >::allocate(allocator_type&, size_type) [with _Tp = int]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/incl
ude/bits/alloc_traits.h:478,
     inlined from 'constexpr std::_Vector_base<_Tp, _Alloc>::pointer 
std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = 
int; _Alloc = std::allocator<int>]' at /home/fdumont/dev/gcc/build/x86_64-
pc-linux-gnu/libstdc++-v3/include/bits/stl_vector.h:380,
     inlined from 'constexpr void std::vector<_Tp, 
_Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, 
std::forward_iterator_tag) [with _ForwardIterator = int*; _Tp = int; 
_Alloc = std::allocator<int
 >]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_vector.h:1694,
     inlined from 'constexpr std::vector<_Tp, 
_Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) 
[with _InputIterator = int*; <template-parameter-2-2> = void; _Tp = int; 
_Alloc = std::allocato
r<int>]' at 
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/stl_vector.h:711,
     inlined from 'void test01()' at 
/home/fdumont/dev/gcc/git/libstdc++-v3/testsuite/25_algorithms/merge/constrained.cc:47:
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/new_allocator.h:151: 
note: returned from 'void* operator new(std::size_t)'
FAIL: 25_algorithms/merge/constrained.cc  -std=gnu++20 (test for excess 
errors)

Just in case there is something to do before gcc 14 release...

François
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
+#else
+  template<typename _Ref1, typename _Ref2>
+    struct _EqualToRefs
     {
-    template<typename _Iterator, typename _Value>
-      _GLIBCXX20_CONSTEXPR
       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)); }
+      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))
-      { }
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
-	: _M_comp(__comp._M_comp)
-      { }
-
-#if __cplusplus >= 201103L
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
-	: _M_comp(std::move(__comp._M_comp))
-      { }
-#endif
-
-      template<typename _Iterator, typename _Value>
-	_GLIBCXX20_CONSTEXPR
       bool
-	operator()(_Iterator __it, _Value& __val)
-	{ return bool(_M_comp(*__it, __val)); }
+      operator()(_Ref __lhs, _Ref __rhs) const
+      { return __lhs == __rhs; }
     };
 
-  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)
-      { }
+  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
-      _Val_comp_iter(_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 _Value, typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Value& __val, _Iterator __it)
-	{ return bool(_M_comp(__val, *__it)); }
-    };
+#if __cplusplus >= 201103L
+  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 _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; }
+      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;
+      template<typename _BPred>
+	constexpr
+	_CompVal(_BPred&& __pred, _Val __val)
+	: _M_binary_pred(std::forward<_BPred>(__pred))
+	, _M_val(__val)
+	{ }
 
-      _GLIBCXX20_CONSTEXPR
-      _Iter_comp_to_val(_Compare __comp, _Value& __value)
-	: _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value)
+      _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)); }
+      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
+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()(_Iterator __it)
-	{ return !bool(_M_pred(*__it)); }
+      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..30fd856b941 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -82,21 +82,22 @@ _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 +108,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 +122,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 +153,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 +164,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 +187,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 +204,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,15 +220,18 @@ _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,
+      return std::__search_n_aux
+	(__first, __last, __count,
+	 _GLIBCXX_FORWARD(_UnaryPredicate, __unary_pred),
 	 std::__iterator_category(__first));
     }
 
@@ -235,7 +243,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;
@@ -243,8 +251,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _ForwardIterator1 __result = __last1;
       while (1)
 	{
-	  _ForwardIterator1 __new_result
-	    = std::__search(__first1, __last1, __first2, __last2, __comp);
+	  _ForwardIterator1 __new_result = std::__search
+	    (__first1, __last1, __first2, __last2, __comp);
 	  if (__new_result == __last1)
 	    return __result;
 	  else
@@ -266,7 +274,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 +287,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 +342,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 +395,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 +418,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 +436,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 +458,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 +481,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 +504,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 +551,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 +598,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 +634,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 +809,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 +844,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 +869,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 +880,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 +911,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 +945,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 +959,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 +971,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 +990,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 +1000,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 +1026,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 +1036,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 +1421,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 +1447,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 +1485,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 +1504,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 +1533,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 +1543,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 +1558,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,
+	std::__stable_partition_adaptive
+	(__first, __last, _GLIBCXX_FORWARD(_Predicate, __pred),
 	 _DistanceType(__buf.requested_size()),
-					 __buf.begin(),
-					 _DistanceType(__buf.size()));
+	 __buf.begin(), _DistanceType(__buf.size()));
     }
 
   /**
@@ -1575,8 +1593,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 +1605,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 +1623,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 +1643,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 +1700,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 +1758,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 +1786,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 +1802,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 +1815,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 +1840,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 +1860,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 +1882,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 +1898,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 +1910,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 +1934,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 +1950,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 +1970,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 +2008,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 +2027,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 +2062,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 +2095,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 +2114,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 +2168,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 +2207,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 +2235,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 +2273,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 +2285,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 +2315,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 				   _BidirectionalIterator2 __first2,
 				   _BidirectionalIterator2 __last2,
 				   _BidirectionalIterator3 __result,
-				   _Compare __comp)
+				   _GLIBCXX_FWDREF(_Compare) __comp)
     {
       if (__first1 == __last1)
 	{
@@ -2294,7 +2329,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 +2395,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 +2425,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 +2443,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 +2468,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 +2481,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 +2503,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 +2521,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 +2530,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 +2551,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 +2602,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 +2646,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 +2656,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 +2673,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 +2682,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 +2697,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 +2707,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 +2725,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 +2739,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 +2753,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 +2771,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 +2811,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 +2827,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 +2879,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 +2928,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 +2945,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 +2961,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 +3006,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 +3041,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 +3064,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 +3110,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 +3145,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 +3157,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 +3197,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 +3235,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 +3266,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 +3307,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 +3333,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 +3378,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 +3386,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 +3405,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 +3458,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 +3487,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 +3498,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 +3509,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 +3543,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 +3553,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 +3574,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 +3595,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 +3633,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 +3662,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 +3906,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 +3934,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 +4038,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 +4068,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 +4091,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 +4116,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 +4160,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 +4192,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 +4229,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 +4490,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 +4532,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 +4648,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 +4686,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 +4728,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 +4764,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 +4806,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 +4838,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 +4873,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,
@@ -4814,7 +4886,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = *__first2;
 	      ++__first2;
@@ -4872,9 +4944,9 @@ _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());
+      return _GLIBCXX_STD_A::__merge
+	(__first1, __last1, __first2, __last2, __result,
+	 __gnu_cxx::__ops::__less(__first1, __first2));
     }
 
   /**
@@ -4925,13 +4997,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__merge(__first1, __last1,
 				     __first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				     _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 +5020,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 +5065,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 +5102,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 +5112,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 +5183,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 +5235,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 +5246,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 +5306,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 +5357,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 +5368,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 +5431,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 +5484,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 +5498,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 +5566,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 +5620,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 +5658,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 +5686,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 +5723,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 +5751,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 +5764,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 +5774,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 +5784,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 +5794,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..7c656fa6637 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));
     }
 
@@ -134,10 +135,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     __push_heap(_RandomAccessIterator __first,
 		_Distance __holeIndex, _Distance __topIndex, _Tp __value,
-		_Compare& __comp)
+		_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;
@@ -174,8 +175,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 +212,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 +223,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
-		  _Distance __len, _Tp __value, _Compare __comp)
+		  _Distance __len, _Tp __value,
+		  _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 +244,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 						     + (__secondChild - 1)));
 	  __holeIndex = __secondChild - 1;
 	}
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
-	__cmp(_GLIBCXX_MOVE(__comp));
-      std::__push_heap(__first, __holeIndex, __topIndex,
-		       _GLIBCXX_MOVE(__value), __cmp);
+      __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),
+		       _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 +265,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 +299,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 +332,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 +341,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 +385,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 +412,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 +450,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 +478,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 +505,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 +533,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 +572,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..8e0f2c969c4 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)));
+					std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -124,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to_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 766558b3ce0..1d6c5c2b4f8 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>
@@ -1116,57 +1119,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..b7d06f9d37b 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)));
+					std::move(__pred));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
@@ -113,7 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __cont.end();
       auto __removed = std::__remove_if(__cont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__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..877627483be 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)));
+					std::move(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -138,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to_val(__value));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h
index e9933373ed9..dc8920ed5f8 100644
--- a/libstdc++-v3/include/bits/predefined_ops.h
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -32,376 +32,170 @@ 
 
 #include <bits/move.h>
 
+#if __cplusplus >= 201103L
+# include <bits/invoke.h>
+#endif
+
 namespace __gnu_cxx
 {
 namespace __ops
 {
-  struct _Iter_less_iter
+  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()(const _Lhs& __lhs, const _Rhs& __rhs) const
+      { return __lhs < __rhs; }
   };
 
   _GLIBCXX14_CONSTEXPR
-  inline _Iter_less_iter
-  __iter_less_iter()
-  { return _Iter_less_iter(); }
-
-  struct _Iter_less_val
-  {
-#if __cplusplus >= 201103L
-    constexpr _Iter_less_val() = default;
-#else
-    _Iter_less_val() { }
-#endif
-
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Iter_less_val(_Iter_less_iter) { }
-
-    template<typename _Iterator, typename _Value>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it < __val; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_less_val()
-  { return _Iter_less_val(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_comp_val(_Iter_less_iter)
-  { return _Iter_less_val(); }
-
-  struct _Val_less_iter
-  {
-#if __cplusplus >= 201103L
-    constexpr _Val_less_iter() = default;
-#else
-    _Val_less_iter() { }
-#endif
-
-    _GLIBCXX20_CONSTEXPR
-    explicit
-    _Val_less_iter(_Iter_less_iter) { }
-
-    template<typename _Value, typename _Iterator>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Value& __val, _Iterator __it) const
-      { return __val < *__it; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_less_iter()
-  { return _Val_less_iter(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_comp_iter(_Iter_less_iter)
-  { return _Val_less_iter(); }
-
-  struct _Iter_equal_to_iter
-  {
-    template<typename _Iterator1, typename _Iterator2>
-      _GLIBCXX20_CONSTEXPR
-      bool
-      operator()(_Iterator1 __it1, _Iterator2 __it2) const
-      { return *__it1 == *__it2; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_iter
-  __iter_equal_to_iter()
-  { return _Iter_equal_to_iter(); }
+  inline _Less
+  __less()
+  { return _Less(); }
 
-  struct _Iter_equal_to_val
+  struct _Equal_to
   {
-    template<typename _Iterator, typename _Value>
+    template<typename _Lhs, typename _Rhs>
       _GLIBCXX20_CONSTEXPR
       bool
-      operator()(_Iterator __it, _Value& __val) const
-      { return *__it == __val; }
+      operator()(const _Lhs& __lhs, const _Rhs& __rhs) const
+      { return __lhs == __rhs; }
   };
 
   _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(); }
-
-  template<typename _Compare>
-    struct _Iter_comp_iter
-    {
-      _Compare _M_comp;
-
-      explicit _GLIBCXX14_CONSTEXPR
-      _Iter_comp_iter(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
-
-      template<typename _Iterator1, typename _Iterator2>
-        _GLIBCXX14_CONSTEXPR
-        bool
-        operator()(_Iterator1 __it1, _Iterator2 __it2)
-        { return bool(_M_comp(*__it1, *__it2)); }
-    };
-
-  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
-    {
-      _Compare _M_comp;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
-      { }
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
-	: _M_comp(__comp._M_comp)
-      { }
-
-#if __cplusplus >= 201103L
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
-	: _M_comp(std::move(__comp._M_comp))
-      { }
-#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)); }
+  inline _Equal_to
+  __equal_to()
+  { return _Equal_to(); }
 
-  template<typename _Compare>
-    struct _Val_comp_iter
+  template<typename _Val>
+    struct _Equal_to_val
     {
-      _Compare _M_comp;
+      const _Val& _M_val;
 
       _GLIBCXX20_CONSTEXPR
-      explicit
-      _Val_comp_iter(_Compare __comp)
-	: _M_comp(_GLIBCXX_MOVE(__comp))
+      _Equal_to_val(const _Val& __val)
+      : _M_val(__val)
       { }
 
-      _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))
-      { }
-#endif
-
-      template<typename _Value, typename _Iterator>
+      template<typename _Lhs>
 	_GLIBCXX20_CONSTEXPR
 	bool
-	operator()(_Value& __val, _Iterator __it)
-	{ return bool(_M_comp(__val, *__it)); }
+	operator()(const _Lhs& __lhs) const
+	{ return __lhs == _M_val; }
     };
 
-  template<typename _Compare>
-    _GLIBCXX20_CONSTEXPR
-    inline _Val_comp_iter<_Compare>
-    __val_comp_iter(_Compare __comp)
-    { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
-
-  template<typename _Compare>
+  template<typename _Val>
     _GLIBCXX20_CONSTEXPR
-    inline _Val_comp_iter<_Compare>
-    __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
-    { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
+    inline _Equal_to_val<_Val>
+    __equal_to(const _Val& __val)
+    { return _Equal_to_val<_Val>(__val); }
 
-  template<typename _Value>
-    struct _Iter_equals_val
+  template<typename _BinaryPred, typename _Val>
+    struct _Comp_val
     {
-      _Value& _M_value;
+      _BinaryPred _M_binary_pred;
+      const _Val& _M_val;
 
       _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_val(_Value& __value)
-	: _M_value(__value)
+      _Comp_val(_BinaryPred __binary_pred, const _Val& __val)
+      : _M_binary_pred(_GLIBCXX_MOVE(__binary_pred)), _M_val(__val)
       { }
 
-      template<typename _Iterator>
+      template<typename _Lhs>
 	_GLIBCXX20_CONSTEXPR
 	bool
-	operator()(_Iterator __it)
-	{ return *__it == _M_value; }
+	operator()(const _Lhs& __lhs) const
+	{ return _M_binary_pred(__lhs, _M_val); }
     };
 
-  template<typename _Value>
+  template<typename _BinaryPred, typename _Val>
     _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
-    {
-      _Iterator1 _M_it1;
+    inline _Comp_val<_BinaryPred, _Val>
+    __comp_val(_BinaryPred __pred, const _Val& __val)
+    { return _Comp_val<_BinaryPred, _Val>(_GLIBCXX_MOVE(__pred), __val); }
 
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_equals_iter(_Iterator1 __it1)
-	: _M_it1(__it1)
-      { }
-
-      template<typename _Iterator2>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator2 __it2)
-	{ return *__it2 == *_M_it1; }
-    };
-
-  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
-    {
-      _Predicate _M_pred;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_pred(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
-      { }
-
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_pred(*__it)); }
-    };
-
-  template<typename _Predicate>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_pred<_Predicate>
-    __pred_iter(_Predicate __pred)
-    { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); }
-
-  template<typename _Compare, typename _Value>
-    struct _Iter_comp_to_val
-    {
-      _Compare _M_comp;
-      _Value& _M_value;
-
-      _GLIBCXX20_CONSTEXPR
-      _Iter_comp_to_val(_Compare __comp, _Value& __value)
-	: _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value)
-      { }
+} // namespace __ops
+} // namespace __gnu_cxx
 
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return bool(_M_comp(*__it, _M_value)); }
-    };
 
-  template<typename _Compare, typename _Value>
-    _Iter_comp_to_val<_Compare, _Value>
-    _GLIBCXX20_CONSTEXPR
-    __iter_comp_val(_Compare __comp, _Value &__val)
-    {
-      return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val);
-    }
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  template<typename _Compare, typename _Iterator1>
-    struct _Iter_comp_to_iter
+  /// Generalized negator.
+  template<typename _Fn>
+    class _Not_fn
     {
-      _Compare _M_comp;
-      _Iterator1 _M_it1;
-
-      _GLIBCXX20_CONSTEXPR
-      _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
-	: _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1)
-      { }
+#if __cplusplus >= 201103L
+      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() _GLIBCXX_NOEXCEPT_IF(noexcept(!std::declval<_Tp>()));
+
+    public:
+      template<typename _Fn2>
+	_GLIBCXX14_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;
+#else
+    public:
+      _Not_fn(_Fn __fn, int)
+      : _M_fn(__fn) { }
+#endif
 
-      template<typename _Iterator2>
-	_GLIBCXX20_CONSTEXPR
+#if __cplusplus >= 201103L
+      // 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>					\
+	_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)...);	\
+	}
+      _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
+      template<typename _Arg>
 	bool
-	operator()(_Iterator2 __it2)
-	{ return bool(_M_comp(*__it2, *_M_it1)); }
-    };
-
-  template<typename _Compare, typename _Iterator>
-    _GLIBCXX20_CONSTEXPR
-    inline _Iter_comp_to_iter<_Compare, _Iterator>
-    __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
-    {
-      return _Iter_comp_to_iter<_Compare, _Iterator>(
-	  _GLIBCXX_MOVE(__comp._M_comp), __it);
-    }
-
-  template<typename _Predicate>
-    struct _Iter_negate
-    {
-      _Predicate _M_pred;
-
-      _GLIBCXX20_CONSTEXPR
-      explicit
-      _Iter_negate(_Predicate __pred)
-	: _M_pred(_GLIBCXX_MOVE(__pred))
-      { }
+	operator()(const _Arg& __arg)
+	{ return !bool(_M_fn(__arg)); }
+#endif
 
-      template<typename _Iterator>
-	_GLIBCXX20_CONSTEXPR
-	bool
-	operator()(_Iterator __it)
-	{ return !bool(_M_pred(*__it)); }
+    private:
+      _Fn _M_fn;
     };
 
-  template<typename _Predicate>
+#if __cplusplus >= 201103L
+  template<typename _Fn>
     _GLIBCXX20_CONSTEXPR
-    inline _Iter_negate<_Predicate>
-    __negate(_Iter_pred<_Predicate> __pred)
-    { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); }
+    inline _Not_fn<std::__decay_t<_Fn>>
+    __not_fn(_Fn&& __fn)
+    noexcept(std::is_nothrow_constructible<std::__decay_t<_Fn>, _Fn&&>::value)
+    { return _Not_fn<std::__decay_t<_Fn>>{std::forward<_Fn>(__fn), 0}; }
+#else
+  template<typename _Fn>
+    inline _Not_fn<_Fn>
+    __not_fn(_Fn __fn)
+    { return _Not_fn<_Fn>(__fn, 0); }
+#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 2c52ed51402..aac29c29820 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -85,18 +85,18 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
 			   _Iterator __c, _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);
@@ -110,7 +110,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		  _Predicate __pred)
     {
       return std::__find_if(__first, __last,
-			    __gnu_cxx::__ops::__negate(__pred),
+			    std::__not_fn(_GLIBCXX_MOVE(__pred)),
 			    std::__iterator_category(__first));
     }
 
@@ -123,7 +123,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
     {
       for (; __len; --__len,  (void) ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  break;
       return __first;
     }
@@ -160,7 +160,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;
@@ -199,7 +199,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
@@ -337,7 +337,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::__find_end(__first1, __last1, __first2, __last2,
 			     std::__iterator_category(__first1),
 			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+			     __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -388,7 +388,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::__find_end(__first1, __last1, __first2, __last2,
 			     std::__iterator_category(__first1),
 			     std::__iterator_category(__first2),
-			     __gnu_cxx::__ops::__iter_comp_iter(__comp));
+			     _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -408,7 +408,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +426,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +448,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _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 +471,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 +494,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,7 +541,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
       return __first;
     }
-#endif
+#endif // C++11
 
   template<typename _InputIterator, typename _OutputIterator,
 	   typename _Predicate>
@@ -549,7 +551,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		     _OutputIterator __result, _Predicate __pred)
     {
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = *__first;
 	    ++__result;
@@ -586,7 +588,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__remove_copy_if(__first, __last, __result,
-	__gnu_cxx::__ops::__iter_equals_val(__value));
+				   __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -620,7 +622,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
@@ -796,7 +798,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__remove_if(__first, __last,
-		__gnu_cxx::__ops::__iter_equals_val(__value));
+			      __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -829,8 +831,7 @@  _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>
@@ -844,7 +845,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _ForwardIterator __next = __first;
       while (++__next != __last)
 	{
-	  if (__binary_pred(__first, __next))
+	  if (__binary_pred(*__first, *__next))
 	    return __first;
 	  __first = __next;
 	}
@@ -866,7 +867,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;
     }
@@ -898,7 +899,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__unique(__first, __last,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+			   __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -930,8 +931,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));
     }
 
   /**
@@ -956,7 +956,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;
@@ -984,12 +984,9 @@  _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;
       while (++__first != __last)
-	if (!__rebound_pred(__first, __value))
+	if (!__binary_pred(*__first, __value))
 	  {
 	    __value = *__first;
 	    *++__result = __value;
@@ -1017,7 +1014,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;
     }
@@ -1479,7 +1476,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  ++__result2;
 	  ++__first;
 	  for (; __first != __last; ++__first)
-	    if (__pred(__first))
+	    if (__pred(*__first))
 	      {
 		*__result1 = _GLIBCXX_MOVE(*__first);
 		++__result1;
@@ -1534,7 +1531,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _Temporary_buffer<_ForwardIterator, _ValueType>
 	__buf(__first, std::distance(__first, __last));
       return
-	std::__stable_partition_adaptive(__first, __last, __pred,
+	std::__stable_partition_adaptive(__first, __last, _GLIBCXX_MOVE(__pred),
 					 _DistanceType(__buf.requested_size()),
 					 __buf.begin(),
 					 _DistanceType(__buf.size()));
@@ -1569,8 +1566,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
 
@@ -1586,7 +1582,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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);
     }
 
@@ -1619,14 +1615,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_MOVE(__comp));
       return __result_real_last;
     }
 
@@ -1677,7 +1674,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       return std::__partial_sort_copy(__first, __last,
 				      __result_first, __result_last,
-				      __gnu_cxx::__ops::__iter_less_iter());
+				      __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -1732,7 +1729,7 @@  _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
@@ -1748,7 +1745,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	__val = _GLIBCXX_MOVE(*__last);
       _RandomAccessIterator __next = __last;
       --__next;
-      while (__comp(__val, __next))
+      while (__comp(__val, *__next))
 	{
 	  *__last = _GLIBCXX_MOVE(*__next);
 	  __last = __next;
@@ -1764,11 +1761,12 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     __insertion_sort(_RandomAccessIterator __first,
 		     _RandomAccessIterator __last, _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);
@@ -1776,8 +1774,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	      *__first = _GLIBCXX_MOVE(__val);
 	    }
 	  else
-	    std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	    std::__unguarded_linear_insert(__i, __comp);
 	}
     }
 
@@ -1789,8 +1786,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 			       _RandomAccessIterator __last, _Compare __comp)
     {
       for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
-	std::__unguarded_linear_insert(__i,
-				__gnu_cxx::__ops::__val_comp_iter(__comp));
+	std::__unguarded_linear_insert(__i, __comp);
     }
 
   /**
@@ -1810,10 +1806,10 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
 	  std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
-					  __comp);
+					  _GLIBCXX_MOVE(__comp));
 	}
       else
-	std::__insertion_sort(__first, __last, __comp);
+	std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function...
@@ -1826,10 +1822,10 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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;
@@ -1848,7 +1844,8 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _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);
+      return std::__unguarded_partition(__first + 1, __last, __first,
+					_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
@@ -1860,7 +1857,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 		   _Compare __comp)
     {
       std::__heap_select(__first, __middle, __last, __comp);
-      std::__sort_heap(__first, __middle, __comp);
+      std::__sort_heap(__first, __middle, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function for the sort routine.
@@ -1899,7 +1896,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  std::__introsort_loop(__first, __last,
 				std::__lg(__last - __first) * 2,
 				__comp);
-	  std::__final_insertion_sort(__first, __last, __comp);
+	  std::__final_insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
 	}
     }
 
@@ -1927,7 +1924,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  else
 	    __last = __cut;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   /// @endcond
@@ -1964,8 +1961,7 @@  _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>
@@ -1984,7 +1980,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
 	    {
@@ -2020,7 +2016,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
 
       return std::__upper_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__val_less_iter());
+				__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2051,17 +2047,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, _Comp __comp)
     {
       typedef typename iterator_traits<_ForwardIterator>::difference_type
 	_DistanceType;
@@ -2073,21 +2066,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_MOVE(__comp));
 	      return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
 	    }
 	}
@@ -2127,8 +2121,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __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());
+				__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2165,9 +2158,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));
     }
 
   /**
@@ -2197,7 +2188,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       _ForwardIterator __i
 	= std::__lower_bound(__first, __last, __val,
-			     __gnu_cxx::__ops::__iter_less_val());
+			     __gnu_cxx::__ops::__less());
       return __i != __last && !(__val < *__i);
     }
 
@@ -2232,8 +2223,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));
     }
 
@@ -2249,7 +2239,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2288,7 +2278,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,13 +2350,14 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
 	  std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
-				     __first, __comp);
+				     __first, _GLIBCXX_MOVE(__comp));
 	}
       else
 	{
 	  _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
 	  std::__move_merge_adaptive_backward(__first, __middle, __buffer,
-					      __buffer_end, __last, __comp);
+					      __buffer_end, __last,
+					      _GLIBCXX_MOVE(__comp));
 	}
     }
 
@@ -2382,7 +2373,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       if (__len1 <= __buffer_size || __len2 <= __buffer_size)
 	std::__merge_adaptive(__first, __middle, __last,
-			      __len1, __len2, __buffer, __comp);
+			      __len1, __len2, __buffer, _GLIBCXX_MOVE(__comp));
       else
 	{
 	  _BidirectionalIterator __first_cut = __first;
@@ -2394,8 +2385,7 @@  _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));
+		= std::__lower_bound(__middle, __last, *__first_cut, __comp);
 	      __len22 = std::distance(__middle, __second_cut);
 	    }
 	  else
@@ -2403,8 +2393,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	      __len22 = __len2 / 2;
 	      std::advance(__second_cut, __len22);
 	      __first_cut
-		= std::__upper_bound(__first, __middle, *__second_cut,
-				     __gnu_cxx::__ops::__val_comp_iter(__comp));
+		= std::__upper_bound(__first, __middle, *__second_cut, __comp);
 	      __len11 = std::distance(__first, __first_cut);
 	    }
 
@@ -2418,7 +2407,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_MOVE(__comp));
 	}
     }
 
@@ -2437,7 +2427,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       if (__len1 + __len2 == 2)
 	{
-	  if (__comp(__middle, __first))
+	  if (__comp(*__middle, *__first))
 	    std::iter_swap(__first, __middle);
 	  return;
 	}
@@ -2451,8 +2441,7 @@  _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));
+	    = std::__lower_bound(__middle, __last, *__first_cut, __comp);
 	  __len22 = std::distance(__middle, __second_cut);
 	}
       else
@@ -2460,8 +2449,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  __len22 = __len2 / 2;
 	  std::advance(__second_cut, __len22);
 	  __first_cut
-	    = std::__upper_bound(__first, __middle, *__second_cut,
-				 __gnu_cxx::__ops::__val_comp_iter(__comp));
+	    = std::__upper_bound(__first, __middle, *__second_cut, __comp);
 	  __len11 = std::distance(__first, __first_cut);
 	}
 
@@ -2470,7 +2458,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_MOVE(__comp));
     }
 
   template<typename _BidirectionalIterator, typename _Compare>
@@ -2498,18 +2487,18 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       _TmpBuf __buf(__first, std::min(__len1, __len2));
 
       if (__builtin_expect(__buf.size() == __buf.requested_size(), true))
-	std::__merge_adaptive
-	  (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp);
+	std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
+			      __buf.begin(), _GLIBCXX_MOVE(__comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
-	std::__merge_without_buffer
-	  (__first, __middle, __last, __len1, __len2, __comp);
+	std::__merge_without_buffer(__first, __middle, __last, __len1, __len2,
+				    _GLIBCXX_MOVE(__comp));
       else
-	std::__merge_adaptive_resize
-	  (__first, __middle, __last, __len1, __len2, __buf.begin(),
-	   _DistanceType(__buf.size()), __comp);
+	std::__merge_adaptive_resize(__first, __middle, __last, __len1, __len2,
+				     __buf.begin(), _DistanceType(__buf.size()),
+				     _GLIBCXX_MOVE(__comp));
 #else
       std::__merge_without_buffer
-	(__first, __middle, __last, __len1, __len2, __comp);
+	(__first, __middle, __last, __len1, __len2, _GLIBCXX_MOVE(__comp));
 #endif
     }
 
@@ -2547,7 +2536,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       std::__inplace_merge(__first, __middle, __last,
-			   __gnu_cxx::__ops::__iter_less_iter());
+			   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2589,8 +2578,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));
     }
 
 
@@ -2604,7 +2592,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = _GLIBCXX_MOVE(*__first2);
 	      ++__first2;
@@ -2617,8 +2605,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,
@@ -2642,7 +2629,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_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Distance,
@@ -2658,7 +2646,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 	  std::__insertion_sort(__first, __first + __chunk_size, __comp);
 	  __first += __chunk_size;
 	}
-      std::__insertion_sort(__first, __last, __comp);
+      std::__insertion_sort(__first, __last, _GLIBCXX_MOVE(__comp));
     }
 
   enum { _S_chunk_size = 7 };
@@ -2724,11 +2712,11 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 				       _Distance(__middle - __first),
 				       _Distance(__last - __middle),
 				       __buffer, __buffer_size,
-				       __comp);
+				       _GLIBCXX_MOVE(__comp));
 	}
       else
 	std::__stable_sort_adaptive(__first, __middle, __last,
-				    __buffer, __comp);
+				    __buffer, _GLIBCXX_MOVE(__comp));
     }
 
   /// This is a helper function for the stable sorting routines.
@@ -2748,7 +2736,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       std::__merge_without_buffer(__first, __middle, __last,
 				  __middle - __first,
 				  __last - __middle,
-				  __comp);
+				  _GLIBCXX_MOVE(__comp));
     }
 
   // stable_sort
@@ -2768,9 +2756,9 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     {
       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;
 	}
@@ -2817,7 +2805,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return std::__includes(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_less_iter());
+			     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2864,7 +2852,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
@@ -2896,10 +2884,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,
@@ -2942,7 +2930,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__next_permutation
-	(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+	(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -2975,8 +2963,7 @@  _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>
@@ -2998,10 +2985,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,
@@ -3045,7 +3032,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_irreflexive(__first, __last);
 
       return std::__prev_permutation(__first, __last,
-				     __gnu_cxx::__ops::__iter_less_iter());
+				     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3078,8 +3065,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
@@ -3094,7 +3080,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 		      _Predicate __pred, const _Tp& __new_value)
     {
       for (; __first != __last; ++__first, (void)++__result)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  *__result = __new_value;
 	else
 	  *__result = *__first;
@@ -3131,8 +3117,8 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__replace_copy_if(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_equals_val(__old_value),
-					      __new_value);
+				    __gnu_cxx::__ops::__equal_to(__old_value),
+				    __new_value);
     }
 
   /**
@@ -3167,8 +3153,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
@@ -3199,7 +3184,9 @@  _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
@@ -3212,7 +3199,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
       _ForwardIterator __next = __first;
       for (++__next; __next != __last; __first = __next, (void)++__next)
-	if (__comp(__next, __first))
+	if (__comp(*__next, *__first))
 	  return __next;
       return __next;
     }
@@ -3238,7 +3225,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());
     }
 
   /**
@@ -3264,8 +3251,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));
     }
 
   /**
@@ -3318,7 +3304,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;
@@ -3337,25 +3323,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;
 	    }
 
@@ -3389,8 +3375,7 @@  _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      return std::__minmax_element(__first, __last,
-				   __gnu_cxx::__ops::__iter_less_iter());
+      return std::__minmax_element(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -3419,8 +3404,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>
@@ -3431,7 +3415,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);
     }
 
@@ -3442,8 +3426,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);
     }
 
@@ -3477,7 +3460,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
@@ -3508,7 +3491,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)
@@ -3529,14 +3512,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::__comp_val(__pred, *__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::__comp_val(__pred, *__scan));
 	  if (0 == __matches
 	      || std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+			__gnu_cxx::__ops::__comp_val(__pred, *__scan))
 	      != __matches)
 	    return false;
 	}
@@ -3567,7 +3550,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());
     }
 
   /**
@@ -3596,7 +3579,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));
     }
 
 #if __cplusplus >= 201703L
@@ -3844,7 +3827,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		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));
+			    __gnu_cxx::__ops::__equal_to(__val));
     }
 
   /**
@@ -3869,8 +3852,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));
     }
 
   /**
@@ -3975,7 +3957,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__adjacent_find(__first, __last,
-				  __gnu_cxx::__ops::__iter_equal_to_iter());
+				  __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -4003,7 +3985,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));
     }
 
   /**
@@ -4027,7 +4009,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__count_if(__first, __last,
-			     __gnu_cxx::__ops::__iter_equals_val(__value));
+			     __gnu_cxx::__ops::__equal_to(__value));
     }
 
   /**
@@ -4050,8 +4032,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));
     }
 
   /**
@@ -4096,7 +4077,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__search(__first1, __last1, __first2, __last2,
-			   __gnu_cxx::__ops::__iter_equal_to_iter());
+			   __gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -4127,7 +4108,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__search_n(__first, __last, __count,
-			     __gnu_cxx::__ops::__iter_equals_val(__val));
+			     __gnu_cxx::__ops::__equal_to(__val));
     }
 
 
@@ -4163,7 +4144,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first, __last);
 
       return std::__search_n(__first, __last, __count,
-		__gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
+	__gnu_cxx::__ops::__comp_val(_GLIBCXX_MOVE(__binary_pred), __val));
     }
 
 #if __cplusplus >= 201703L
@@ -4420,7 +4401,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last)
 	return __result;
       return std::__unique_copy(__first, __last, __result,
-				__gnu_cxx::__ops::__iter_equal_to_iter(),
+				__gnu_cxx::__ops::__equal_to(),
 				std::__iterator_category(__first),
 				std::__iterator_category(__result));
     }
@@ -4460,7 +4441,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last)
 	return __result;
       return std::__unique_copy(__first, __last, __result,
-			__gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
+				_GLIBCXX_MOVE(__binary_pred),
 				std::__iterator_category(__first),
 				std::__iterator_category(__result));
     }
@@ -4576,7 +4557,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));
     }
 
@@ -4615,7 +4596,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       std::__partial_sort(__first, __middle, __last,
-			  __gnu_cxx::__ops::__iter_less_iter());
+			  __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4655,8 +4636,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));
     }
 
   /**
@@ -4694,7 +4674,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       std::__introselect(__first, __nth, __last,
 			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_less_iter());
+			 __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4735,7 +4715,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       std::__introselect(__first, __nth, __last,
 			 std::__lg(__last - __first) * 2,
-			 __gnu_cxx::__ops::__iter_comp_iter(__comp));
+			 _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -4765,7 +4745,7 @@  _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());
+      std::__sort(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4798,7 +4778,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,
@@ -4811,7 +4791,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       while (__first1 != __last1 && __first2 != __last2)
 	{
-	  if (__comp(__first2, __first1))
+	  if (__comp(*__first2, *__first1))
 	    {
 	      *__result = *__first2;
 	      ++__first2;
@@ -4871,7 +4851,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__merge(__first1, __last1,
 				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+				     __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -4921,8 +4901,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
       return _GLIBCXX_STD_A::__merge(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				     __first2, __last2, __result,
+				     _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
@@ -4947,14 +4927,16 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__builtin_expect(__buf.requested_size() == __buf.size(), true))
 	std::__stable_sort_adaptive(__first,
 				    __first + _DistanceType(__buf.size()),
-				    __last, __buf.begin(), __comp);
+				    __last, __buf.begin(),
+				    _GLIBCXX_MOVE(__comp));
       else if (__builtin_expect(__buf.begin() == 0, false))
-	std::__inplace_stable_sort(__first, __last, __comp);
+	std::__inplace_stable_sort(__first, __last, _GLIBCXX_MOVE(__comp));
       else
 	std::__stable_sort_adaptive_resize(__first, __last, __buf.begin(),
-					   _DistanceType(__buf.size()), __comp);
+					   _DistanceType(__buf.size()),
+					   _GLIBCXX_MOVE(__comp));
 #else
-      std::__inplace_stable_sort(__first, __last, __comp);
+      std::__inplace_stable_sort(__first, __last, _GLIBCXX_MOVE(__comp));
 #endif
     }
 
@@ -4988,7 +4970,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_less_iter());
+				    __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5024,7 +5006,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       _GLIBCXX_STD_A::__stable_sort(__first, __last,
-				    __gnu_cxx::__ops::__iter_comp_iter(__comp));
+				    _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5038,12 +5020,12 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
     {
       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;
@@ -5106,8 +5088,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_union(__first1, __last1,
-				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_less_iter());
+					 __first2, __last2, __result,
+					 __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5157,8 +5139,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+					 __first2, __last2, __result,
+					 _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5171,9 +5153,9 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		       _OutputIterator __result, _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
 	  {
@@ -5228,8 +5210,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
-				     __first2, __last2, __result,
-				     __gnu_cxx::__ops::__iter_less_iter());
+						__first2, __last2, __result,
+						__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5278,8 +5260,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+						__first2, __last2, __result,
+						_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5292,13 +5274,13 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 		     _OutputIterator __result, _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
 	  {
@@ -5353,8 +5335,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
-				   __first2, __last2, __result,
-				   __gnu_cxx::__ops::__iter_less_iter());
+					      __first2, __last2, __result,
+					      __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5405,8 +5387,8 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __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));
+					      __first2, __last2, __result,
+					      _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _InputIterator1, typename _InputIterator2,
@@ -5422,13 +5404,13 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 			       _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;
@@ -5489,7 +5471,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
 					__first2, __last2, __result,
-					__gnu_cxx::__ops::__iter_less_iter());
+					__gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5542,7 +5524,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
 				__first2, __last2, __result,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+				_GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
@@ -5555,7 +5537,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__first, __result))
+	if (__comp(*__first, *__result))
 	  __result = __first;
       return __result;
     }
@@ -5580,7 +5562,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+					   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5607,7 +5589,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       return _GLIBCXX_STD_A::__min_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+					   _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _ForwardIterator, typename _Compare>
@@ -5619,7 +5601,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       if (__first == __last) return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
-	if (__comp(__result, __first))
+	if (__comp(*__result, *__first))
 	  __result = __first;
       return __result;
     }
@@ -5644,7 +5626,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive(__first, __last);
 
       return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_less_iter());
+					   __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -5671,7 +5653,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
 
       return _GLIBCXX_STD_A::__max_element(__first, __last,
-				__gnu_cxx::__ops::__iter_comp_iter(__comp));
+					   _GLIBCXX_MOVE(__comp));
     }
 
 #if __cplusplus >= 201103L
@@ -5683,7 +5665,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>
@@ -5693,7 +5675,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>
@@ -5703,7 +5685,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>
@@ -5713,7 +5695,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 dd95e94f7e9..f521ac118f3 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -1300,9 +1300,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;
@@ -1316,10 +1316,9 @@  _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());
+						__gnu_cxx::__ops::__less());
 	}
 
       template<typename _II1, typename _II2>
@@ -1469,7 +1468,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;
@@ -1505,7 +1504,7 @@  _GLIBCXX_END_NAMESPACE_CONTAINER
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
 
       return std::__lower_bound(__first, __last, __val,
-				__gnu_cxx::__ops::__iter_less_val());
+				__gnu_cxx::__ops::__less());
     }
 
   /// This is a helper function for the sort routines and for random.tcc.
@@ -1637,7 +1636,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	  if (__d1 != __d2)
 	    return false;
 	  return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
-				       __binary_pred);
+				       std::move(__binary_pred));
 	}
 
       for (; __first1 != __last1 && __first2 != __last2;
@@ -1778,8 +1777,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
@@ -1884,7 +1882,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
     __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
 	       _InputIterator2 __first2, _BinaryPredicate __binary_pred)
     {
-      while (__first1 != __last1 && __binary_pred(__first1, __first2))
+      while (__first1 != __last1 && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -1920,7 +1918,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first1, __last1);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+					__gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -1952,7 +1950,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 __cplusplus > 201103L
@@ -1966,7 +1964,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
 	       _BinaryPredicate __binary_pred)
     {
       while (__first1 != __last1 && __first2 != __last2
-	     && __binary_pred(__first1, __first2))
+	     && __binary_pred(*__first1, *__first2))
 	{
 	  ++__first1;
 	  ++__first2;
@@ -2004,7 +2002,7 @@  _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
-			     __gnu_cxx::__ops::__iter_equal_to_iter());
+					__gnu_cxx::__ops::__equal_to());
     }
 
   /**
@@ -2039,7 +2037,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
 
@@ -2052,7 +2050,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
     __find_if(_InputIterator __first, _InputIterator __last,
 	      _Predicate __pred, input_iterator_tag)
     {
-      while (__first != __last && !__pred(__first))
+      while (__first != __last && !__pred(*__first))
 	++__first;
       return __first;
     }
@@ -2069,19 +2067,19 @@  _GLIBCXX_END_NAMESPACE_ALGO
 
       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;
 	}
@@ -2089,17 +2087,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
@@ -2125,7 +2123,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
     {
       typename iterator_traits<_InputIterator>::difference_type __n = 0;
       for (; __first != __last; ++__first)
-	if (__pred(__first))
+	if (__pred(*__first))
 	  ++__n;
       return __n;
     }
@@ -2142,7 +2140,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
       _ForwardIterator __result = __first;
       ++__first;
       for (; __first != __last; ++__first)
-	if (!__pred(__first))
+	if (!__pred(*__first))
 	  {
 	    *__result = _GLIBCXX_MOVE(*__first);
 	    ++__result;
@@ -2156,7 +2154,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
     _ForwardIterator1
     __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
 	     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-	     _BinaryPredicate  __predicate)
+	     _BinaryPredicate  __pred)
     {
       // Test for empty ranges
       if (__first1 == __last1 || __first2 == __last2)
@@ -2166,7 +2164,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
       _ForwardIterator2 __p1(__first2);
       if (++__p1 == __last2)
 	return std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+	  __gnu_cxx::__ops::__comp_val(_GLIBCXX_MOVE(__pred), *__first2));
 
       // General case.
       _ForwardIterator1 __current = __first1;
@@ -2175,7 +2173,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
 	{
 	  __first1 =
 	    std::__find_if(__first1, __last1,
-		__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+			   __gnu_cxx::__ops::__comp_val(__pred, *__first2));
 
 	  if (__first1 == __last1)
 	    return __last1;
@@ -2185,7 +2183,7 @@  _GLIBCXX_END_NAMESPACE_ALGO
 	  if (++__current == __last1)
 	    return __last1;
 
-	  while (__predicate(__current, __p))
+	  while (__pred(*__current, *__p))
 	    {
 	      if (++__p == __last2)
 		return __first1;
@@ -2208,7 +2206,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)
@@ -2221,15 +2219,15 @@  _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::__comp_val(__pred, *__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::__comp_val(__pred, *__scan));
 	  if (0 == __matches ||
 	      std::__count_if(__scan, __last1,
-			__gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+			      __gnu_cxx::__ops::__comp_val(__pred, *__scan))
 	      != __matches)
 	    return false;
 	}
@@ -2263,7 +2261,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
 
@@ -2308,7 +2306,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 551c3687624..854d1cffd67 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)
+		    _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,8 +94,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline bool
     __is_heap(_RandomAccessIterator __first, _Distance __n)
     {
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      return std::__is_heap_until(__first, __n, __comp) == __n;
+      return std::__is_heap_until(__first, __n,
+				  __gnu_cxx::__ops::__less()) == __n;
     }
 
   template<typename _RandomAccessIterator, typename _Compare,
@@ -104,9 +104,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline bool
     __is_heap(_RandomAccessIterator __first, _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_MOVE(__comp)) == __n;
     }
 
   template<typename _RandomAccessIterator>
@@ -134,10 +133,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     __push_heap(_RandomAccessIterator __first,
 		_Distance __holeIndex, _Distance __topIndex, _Tp __value,
-		_Compare& __comp)
+		_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;
@@ -174,10 +173,10 @@  _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));
       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
-		       _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
+		       _DistanceType(0), _GLIBCXX_MOVE(__value),
+		       __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -210,11 +209,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,
@@ -229,8 +227,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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 +240,15 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 						     + (__secondChild - 1)));
 	  __holeIndex = __secondChild - 1;
 	}
-      __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
-	__cmp(_GLIBCXX_MOVE(__comp));
       std::__push_heap(__first, __holeIndex, __topIndex,
-		       _GLIBCXX_MOVE(__value), __cmp);
+		       _GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp));
     }
 
   template<typename _RandomAccessIterator, typename _Compare>
     _GLIBCXX20_CONSTEXPR
     inline void
     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-	       _RandomAccessIterator __result, _Compare& __comp)
+	       _RandomAccessIterator __result, _Compare __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	_ValueType;
@@ -263,7 +259,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       *__result = _GLIBCXX_MOVE(*__first);
       std::__adjust_heap(__first, _DistanceType(0),
 			 _DistanceType(__last - __first),
-			 _GLIBCXX_MOVE(__value), __comp);
+			 _GLIBCXX_MOVE(__value), _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -295,8 +291,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__last - __first > 1)
 	{
 	  --__last;
-	  __gnu_cxx::__ops::_Iter_less_iter __comp;
-	  std::__pop_heap(__first, __last, __last, __comp);
+	  std::__pop_heap(__first, __last, __last,
+			  __gnu_cxx::__ops::__less());
 	}
     }
 
@@ -327,10 +323,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 +332,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _GLIBCXX20_CONSTEXPR
     void
     __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
-		_Compare& __comp)
+		_Compare __comp)
     {
       typedef typename iterator_traits<_RandomAccessIterator>::value_type
 	  _ValueType;
@@ -382,8 +376,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_valid_range(__first, __last);
       __glibcxx_requires_irreflexive(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      std::__make_heap(__first, __last, __comp);
+      std::__make_heap(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -408,16 +401,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)
+		_Compare __comp)
     {
       while (__last - __first > 1)
 	{
@@ -448,8 +439,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_irreflexive(__first, __last);
       __glibcxx_requires_heap(__first, __last);
 
-      __gnu_cxx::__ops::_Iter_less_iter __comp;
-      std::__sort_heap(__first, __last, __comp);
+      std::__sort_heap(__first, __last, __gnu_cxx::__ops::__less());
     }
 
   /**
@@ -475,9 +465,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 +492,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 +520,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),
+			       _GLIBCXX_MOVE(__comp));
     }
 
   /**
@@ -572,9 +559,8 @@  _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,
+				  _GLIBCXX_MOVE(__comp)) == __dist;
     }
 #endif
 
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index e3d50d2cf8b..df979f853cb 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -97,12 +97,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)));
+					std::ref(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -122,7 +121,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__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 4a4b8b2b2e6..b03b94f2093 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1080,51 +1080,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif // C++20
 
 #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>					\
-	_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)...);	\
-	}
-      _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 dd4ece12801..97cd60b5c2e 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -88,11 +88,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)));
+					std::ref(__pred));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
@@ -106,7 +105,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __cont.end();
       auto __removed = std::__remove_if(__cont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__value));
       __cont.erase(__removed, __end);
       return __osz - __cont.size();
     }
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 712087f1bdd..ea83ce62e2d 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -108,12 +108,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)));
+					std::ref(__pred));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),
@@ -134,7 +133,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       const auto __osz = __cont.size();
       const auto __end = __ucont.end();
       auto __removed = std::__remove_if(__ucont.begin(), __end,
-					__ops::__iter_equals_val(__value));
+					__ops::__equal_to(__value));
       if (__removed != __end)
 	{
 	  __cont.erase(__niter_wrap(__cont.begin(), __removed),