This is a snapshot of work on P2714 "Bind front and back to NTTP
callables", posted for reference. Not tested.

libstdc++-v3/ChangeLog:
        PR libstdc++/119744
        * include/bits/version.def: Redefine __cpp_lib_bind_front etc.
        * include/bits/version.h: Ditto.
        * include/std/functional: Add new bind_front etc. overloads
---
 libstdc++-v3/include/bits/version.def |  6 +-
 libstdc++-v3/include/bits/version.h   | 18 ++---
 libstdc++-v3/include/std/functional   | 96 ++++++++++++++++++++++++++-
 3 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index b89b287e8e8..f8ccfaeb8c3 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -464,7 +464,7 @@ ftms = {
 ftms = {
   name = not_fn;
   values = {
-    v = 201603;
+    v = 202306;
     cxxmin = 17;
   };
 };
@@ -777,7 +777,7 @@ ftms = {
 ftms = {
   name = bind_front;
   values = {
-    v = 201907;
+    v = 202306
     cxxmin = 20;
   };
 };
@@ -785,7 +785,7 @@ ftms = {
 ftms = {
   name = bind_back;
   values = {
-    v = 202202;
+    v = 202306;
     cxxmin = 23;
     extra_cond = "__cpp_explicit_this_parameter";
   };
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index a70a7ede68c..52e6ae2d9b8 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -511,10 +511,10 @@
 #undef __glibcxx_want_make_from_tuple
 
 #if !defined(__cpp_lib_not_fn)
-# if (__cplusplus >= 201703L)
-#  define __glibcxx_not_fn 201603L
+# if (__cplusplus >= 202306L)
+#  define __glibcxx_not_fn 202306L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn)
-#   define __cpp_lib_not_fn 201603L
+#   define __cpp_lib_not_fn 202306L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_not_fn) && defined(__glibcxx_want_not_fn) */
@@ -866,20 +866,20 @@
 #undef __glibcxx_want_atomic_value_initialization
 
 #if !defined(__cpp_lib_bind_front)
-# if (__cplusplus >= 202002L)
-#  define __glibcxx_bind_front 201907L
+# if (__cplusplus >= 202306L)
+#  define __glibcxx_bind_front 202306L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front)
-#   define __cpp_lib_bind_front 201907L
+#   define __cpp_lib_bind_front 202306L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_bind_front) && defined(__glibcxx_want_bind_front) 
*/
 #undef __glibcxx_want_bind_front
 
 #if !defined(__cpp_lib_bind_back)
-# if (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter)
-#  define __glibcxx_bind_back 202202L
+# if (__cplusplus >= 202306L) && (__cpp_explicit_this_parameter)
+#  define __glibcxx_bind_back 202306L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back)
-#   define __cpp_lib_bind_back 202202L
+#   define __cpp_lib_bind_back 202306L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_bind_back) && defined(__glibcxx_want_bind_back) */
diff --git a/libstdc++-v3/include/std/functional 
b/libstdc++-v3/include/std/functional
index 307bcb95bcc..c317d471350 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -940,7 +940,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          _M_bound_args(std::forward<_Args>(__args)...)
        { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); }
 
-#if __cpp_explicit_this_parameter
+#ifdef __cpp_explicit_this_parameter
       template<typename _Self, typename... _CallArgs>
        constexpr
        invoke_result_t<__like_t<_Self, _Fd>, __like_t<_Self, _BoundArgs>..., 
_CallArgs...>
@@ -1049,6 +1049,97 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn),
                                          std::forward<_Args>(__args)...);
     }
+
+#if __cpp_lib_bind_front >= 202306
+
+  template<typename _T, typename _U>
+  struct __copy_const : conditional<is_const_v<_T>, const _U, _U> {};
+
+  template<typename _T, typename _U,
+  class _X = __copy_const<remove_reference_t<_T>, _U>::type>
+
+  struct __copy_value_category
+    : conditional<is_lvalue_reference_v<_T&&>, _X&, _X&&>
+  {};
+
+  template<typename _T, typename _U>
+  struct __type_forward_like : __copy_value_category<_T, 
remove_reference_t<_U>>
+  {};
+
+  template<typename _T, typename _U>
+  using __type_forward_like_t = __type_forward_like<_T, _U>::type;
+
+  /** Create call wrapper by partial application of arguments to function.
+   *
+   * The result of `std::bind_front<f>(args...)` is a function object that
+   * stores `f` and the bound arguments, `args...`. When that function
+   * object is invoked with `call_args...` it returns the result of calling
+   * `f(args..., call_args...)`.
+   *
+   *  @since C++26
+   */
+
+  template<auto __fn, typename... _Args>
+  constexpr auto
+  bind_front(_Args&&... __args)
+    requires (
+      (is_constructible_v<decay_t<_Args>, _Args> and ...) and
+      (is_move_constructible_v<decay_t<_Args>> and ...))
+  {
+    using _Fn = decltype(__fn);
+    if constexpr (is_pointer_v<_Fn> or is_member_pointer_v<_Fn>) {
+      static_assert(__fn != nullptr);
+    }
+    return [... __bound_args(std::forward<_Args>(__args))]<
+            typename _Self, typename... _T>
+      (this _Self&&, _T&&... __call_args)
+      noexcept(is_nothrow_invocable_v<
+       _Fn, __type_forward_like_t<_Self, decay_t<_Args>>..., _T...>)
+      -> invoke_result_t<
+          _Fn, __type_forward_like_t<_Self, decay_t<_Args>>..., _T...>
+      {
+       return invoke(__fn,
+         forward_like<_Self>(__bound_args)...,
+         forward<_T>(__call_args)...);
+      };
+  }
+
+  /** Create call wrapper by partial application of arguments to function.
+   *
+   * The result of `std::bind_back<f>(args...)` is a function object that
+   * stores `f` and the bound arguments, `args...`. When that function
+   * object is invoked with `call_args...` it returns the result of calling
+   * `f(call_args..., args...)`.
+   *
+   *  @since C++26
+   */
+
+  template<auto __fn, typename... _Args>
+  constexpr auto
+  bind_back(_Args&&... __args)
+    requires (
+      (is_constructible_v<decay_t<_Args>, _Args> and ...) and
+      (is_move_constructible_v<decay_t<_Args>> and ...))
+  {
+    using _Fn = decltype(__fn);
+    if constexpr (is_pointer_v<_Fn> or is_member_pointer_v<_Fn>) {
+      static_assert(__fn != nullptr);
+    }
+    return [... __bound_args(std::forward<_Args>(__args))]<
+            typename _Self, typename... _T>
+      (this _Self&&, _T&&... __call_args)
+      noexcept(is_nothrow_invocable_v<
+       _Fn, __type_forward_like_t<_Self, decay_t<_Args>>..., _T...>)
+      -> invoke_result_t<
+          _Fn, __type_forward_like_t<_Self, decay_t<_Args>>..., _T...>
+      {
+       return invoke(__fn,
+         forward<_T>(__call_args)...,
+         forward_like<_Self>(__bound_args)...);
+      };
+  }
+
+#endif // __cpp_lib_bind_front >= 202306, NTTP bind_front
 #endif // __cpp_lib_bind_front
 
 #ifdef __cpp_lib_bind_back // C++ >= 23
@@ -1216,6 +1307,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     not_fn(_Fn&& __fn)
     noexcept(std::is_nothrow_constructible<std::decay_t<_Fn>, _Fn&&>::value)
     {
+      if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>) {
+       static_assert(__fn != nullptr);
+      }
       return _Not_fn<std::decay_t<_Fn>>{std::forward<_Fn>(__fn), 0};
     }
 #endif
-- 
2.50.0

Reply via email to