[libcxx-commits] [libcxx] [libc++] Simplify std::function implementation further (PR #145153)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 21 00:53:50 PDT 2025


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/145153

None

>From 1a5b12a9b8a065522ea0310b53d66f22aff10858 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 17 Jun 2025 06:39:49 +0200
Subject: [PATCH] [libc++] Simplify std::function implementation further

---
 libcxx/include/__functional/function.h | 126 +++++++++++--------------
 1 file changed, 54 insertions(+), 72 deletions(-)

diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index dc112ebfd0faa..22be6a2932b92 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -15,16 +15,14 @@
 #include <__cstddef/nullptr_t.h>
 #include <__exception/exception.h>
 #include <__functional/binary_function.h>
-#include <__functional/invoke.h>
 #include <__functional/unary_function.h>
 #include <__memory/addressof.h>
 #include <__type_traits/aligned_storage.h>
 #include <__type_traits/decay.h>
-#include <__type_traits/is_core_convertible.h>
+#include <__type_traits/invoke.h>
 #include <__type_traits/is_scalar.h>
 #include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/is_trivially_destructible.h>
-#include <__type_traits/is_void.h>
 #include <__type_traits/strip_signature.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
@@ -95,29 +93,29 @@ template <class _Rp, class _A1, class _A2>
 struct __maybe_derive_from_binary_function<_Rp(_A1, _A2)> : public __binary_function<_A1, _A2, _Rp> {};
 
 template <class _Fp>
-_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp const&) {
-  return true;
+_LIBCPP_HIDE_FROM_ABI bool __is_null(_Fp const&) {
+  return false;
 }
 
 template <class _Fp>
-_LIBCPP_HIDE_FROM_ABI bool __not_null(_Fp* __ptr) {
-  return __ptr;
+_LIBCPP_HIDE_FROM_ABI bool __is_null(_Fp* __ptr) {
+  return !__ptr;
 }
 
 template <class _Ret, class _Class>
-_LIBCPP_HIDE_FROM_ABI bool __not_null(_Ret _Class::*__ptr) {
-  return __ptr;
+_LIBCPP_HIDE_FROM_ABI bool __is_null(_Ret _Class::* __ptr) {
+  return !__ptr;
 }
 
 template <class _Fp>
-_LIBCPP_HIDE_FROM_ABI bool __not_null(function<_Fp> const& __f) {
-  return !!__f;
+_LIBCPP_HIDE_FROM_ABI bool __is_null(function<_Fp> const& __f) {
+  return __f;
 }
 
 #  if __has_extension(blocks)
 template <class _Rp, class... _Args>
-_LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) {
-  return __p;
+_LIBCPP_HIDE_FROM_ABI bool __is_null(_Rp (^__p)(_Args...)) {
+  return !__p;
 }
 #  endif
 
@@ -206,12 +204,13 @@ class __value_func<_Rp(_ArgTypes...)> {
   _LIBCPP_HIDE_FROM_ABI explicit __value_func(_Fp&& __f) : __f_(nullptr) {
     typedef __function::__func<_Fp, _Rp(_ArgTypes...)> _Fun;
 
-    if (__function::__not_null(__f)) {
-      if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) {
-        __f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f));
-      } else {
-        __f_ = new _Fun(std::move(__f));
-      }
+    if (__function::__is_null(__f))
+      return;
+
+    if (sizeof(_Fun) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value) {
+      __f_ = ::new (std::addressof(__buf_)) _Fun(std::move(__f));
+    } else {
+      __f_ = new _Fun(std::move(__f));
     }
   }
 
@@ -356,7 +355,31 @@ struct __policy {
   // type.
   template <typename _Fun>
   _LIBCPP_HIDE_FROM_ABI static const __policy* __create() {
-    return __choose_policy<_Fun>(__use_small_storage<_Fun>());
+    if constexpr (__use_small_storage<_Fun>::value) {
+      static constexpr __policy __policy = {
+          nullptr,
+          nullptr,
+          false,
+#  if _LIBCPP_HAS_RTTI
+          &typeid(_Fun)
+#  else
+          nullptr
+#  endif
+      };
+      return &__policy;
+    } else {
+      static constexpr __policy __policy = {
+          std::addressof(__large_clone<_Fun>),
+          std::addressof(__large_destroy<_Fun>),
+          false,
+#  if _LIBCPP_HAS_RTTI
+          &typeid(_Fun)
+#  else
+          nullptr
+#  endif
+      };
+      return &__policy;
+    }
   }
 
   _LIBCPP_HIDE_FROM_ABI static const __policy* __create_empty() {
@@ -384,36 +407,6 @@ struct __policy {
   _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) {
     delete static_cast<_Fun*>(__s);
   }
-
-  template <typename _Fun>
-  _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ false_type) {
-    static constexpr __policy __policy = {
-        std::addressof(__large_clone<_Fun>),
-        std::addressof(__large_destroy<_Fun>),
-        false,
-#  if _LIBCPP_HAS_RTTI
-        &typeid(_Fun)
-#  else
-        nullptr
-#  endif
-    };
-    return &__policy;
-  }
-
-  template <typename _Fun>
-  _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ true_type) {
-    static constexpr __policy __policy = {
-        nullptr,
-        nullptr,
-        false,
-#  if _LIBCPP_HAS_RTTI
-        &typeid(_Fun)
-#  else
-        nullptr
-#  endif
-    };
-    return &__policy;
-  }
 };
 
 // Used to choose between perfect forwarding or pass-by-value. Pass-by-value is
@@ -455,14 +448,15 @@ class __policy_func<_Rp(_ArgTypes...)> {
 
   template <class _Fp, __enable_if_t<!is_same<__decay_t<_Fp>, __policy_func>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) {
-    if (__function::__not_null(__f)) {
-      __func_   = __call_func<_Fp>;
-      __policy_ = __policy::__create<_Fp>();
-      if (__use_small_storage<_Fp>()) {
-        ::new ((void*)&__buf_.__small) _Fp(std::move(__f));
-      } else {
-        __buf_.__large = ::new _Fp(std::move(__f));
-      }
+    if (__function::__is_null(__f))
+      return;
+
+    __func_   = __call_func<_Fp>;
+    __policy_ = __policy::__create<_Fp>();
+    if (__use_small_storage<_Fp>()) {
+      ::new ((void*)&__buf_.__small) _Fp(std::move(__f));
+    } else {
+      __buf_.__large = ::new _Fp(std::move(__f));
     }
   }
 
@@ -615,21 +609,9 @@ class function<_Rp(_ArgTypes...)>
 
   __func __f_;
 
-  template <class _Fp,
-            bool = _And<_IsNotSame<__remove_cvref_t<_Fp>, function>, __is_invocable<_Fp, _ArgTypes...> >::value>
-  struct __callable;
-  template <class _Fp>
-  struct __callable<_Fp, true> {
-    static const bool value =
-        is_void<_Rp>::value || __is_core_convertible<__invoke_result_t<_Fp, _ArgTypes...>, _Rp>::value;
-  };
-  template <class _Fp>
-  struct __callable<_Fp, false> {
-    static const bool value = false;
-  };
-
   template <class _Fp>
-  using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<__callable<_Fp&>::value>;
+  using _EnableIfLValueCallable _LIBCPP_NODEBUG =
+      __enable_if_t<!is_same<__remove_cvref_t<_Fp>, function>::value && __is_invocable_r_v<_Fp, _ArgTypes...>>;
 
 public:
   typedef _Rp result_type;



More information about the libcxx-commits mailing list