[libcxx-commits] [libcxx] 2050d2e - [libc++] Simplify std::function further after removing allocator support (#144443)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 21 00:47:56 PDT 2025


Author: Nikolas Klauser
Date: 2025-06-21T09:47:54+02:00
New Revision: 2050d2e1815b4b306f4b3842d6ac0fa73e1d4085

URL: https://github.com/llvm/llvm-project/commit/2050d2e1815b4b306f4b3842d6ac0fa73e1d4085
DIFF: https://github.com/llvm/llvm-project/commit/2050d2e1815b4b306f4b3842d6ac0fa73e1d4085.diff

LOG: [libc++] Simplify std::function further after removing allocator support (#144443)

Since we've removed allocator support, we can remove a few support
structures. This only affects the policy implementation, so this
shouldn't even be ABI sensitive.

Added: 
    

Modified: 
    libcxx/include/__functional/function.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index e71c778386fd2..dc112ebfd0faa 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -125,31 +125,6 @@ _LIBCPP_HIDE_FROM_ABI bool __not_null(_Rp (^__p)(_Args...)) {
 
 namespace __function {
 
-template <class _Fp, class _FB>
-class __default_alloc_func;
-
-template <class _Fp, class _Rp, class... _ArgTypes>
-class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
-  _Fp __f_;
-
-public:
-  using _Target _LIBCPP_NODEBUG = _Fp;
-
-  _LIBCPP_HIDE_FROM_ABI const _Target& __target() const { return __f_; }
-
-  _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(_Target&& __f) : __f_(std::move(__f)) {}
-
-  _LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(const _Target& __f) : __f_(__f) {}
-
-  _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
-    return std::__invoke_r<_Rp>(__f_, std::forward<_ArgTypes>(__arg)...);
-  }
-
-  _LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const { return new __default_alloc_func(__f_); }
-
-  _LIBCPP_HIDE_FROM_ABI void destroy() _NOEXCEPT { __f_.~_Target(); }
-};
-
 // __base provides an abstract interface for copyable functors.
 
 template <class _Fp>
@@ -402,7 +377,7 @@ struct __policy {
   template <typename _Fun>
   _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) {
     const _Fun* __f = static_cast<const _Fun*>(__s);
-    return __f->__clone();
+    return new _Fun(*__f);
   }
 
   template <typename _Fun>
@@ -417,7 +392,7 @@ struct __policy {
         std::addressof(__large_destroy<_Fun>),
         false,
 #  if _LIBCPP_HAS_RTTI
-        &typeid(typename _Fun::_Target)
+        &typeid(_Fun)
 #  else
         nullptr
 #  endif
@@ -432,7 +407,7 @@ struct __policy {
         nullptr,
         false,
 #  if _LIBCPP_HAS_RTTI
-        &typeid(typename _Fun::_Target)
+        &typeid(_Fun)
 #  else
         nullptr
 #  endif
@@ -446,42 +421,7 @@ struct __policy {
 template <typename _Tp>
 using __fast_forward _LIBCPP_NODEBUG = __conditional_t<is_scalar<_Tp>::value, _Tp, _Tp&&>;
 
-// __policy_invoker calls an instance of __default_alloc_func held in __policy_storage.
-
-template <class _Fp>
-struct __policy_invoker;
-
-template <class _Rp, class... _ArgTypes>
-struct __policy_invoker<_Rp(_ArgTypes...)> {
-  typedef _Rp (*__Call)(const __policy_storage*, __fast_forward<_ArgTypes>...);
-
-  __Call __call_;
-
-  // Creates an invoker that throws bad_function_call.
-  _LIBCPP_HIDE_FROM_ABI __policy_invoker() : __call_(&__call_empty) {}
-
-  // Creates an invoker that calls the given instance of __func.
-  template <typename _Fun>
-  _LIBCPP_HIDE_FROM_ABI static __policy_invoker __create() {
-    return __policy_invoker(std::addressof(__call_impl<_Fun>));
-  }
-
-private:
-  _LIBCPP_HIDE_FROM_ABI explicit __policy_invoker(__Call __c) : __call_(__c) {}
-
-  _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) {
-    std::__throw_bad_function_call();
-  }
-
-  template <typename _Fun>
-  _LIBCPP_HIDE_FROM_ABI static _Rp __call_impl(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) {
-    _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large);
-    return (*__f)(std::forward<_ArgTypes>(__args)...);
-  }
-};
-
-// __policy_func uses a __policy and __policy_invoker to create a type-erased,
-// copyable functor.
+// __policy_func uses a __policy to create a type-erased, copyable functor.
 
 template <class _Fp>
 class __policy_func;
@@ -491,45 +431,52 @@ class __policy_func<_Rp(_ArgTypes...)> {
   // Inline storage for small objects.
   __policy_storage __buf_;
 
-  // Calls the value stored in __buf_. This could technically be part of
-  // policy, but storing it here eliminates a level of indirection inside
-  // operator().
-  typedef __function::__policy_invoker<_Rp(_ArgTypes...)> __invoker;
-  __invoker __invoker_;
+  using _ErasedFunc _LIBCPP_NODEBUG = _Rp(const __policy_storage*, __fast_forward<_ArgTypes>...);
+
+  _ErasedFunc* __func_;
 
   // The policy that describes how to move / copy / destroy __buf_. Never
   // null, even if the function is empty.
   const __policy* __policy_;
 
+  _LIBCPP_HIDE_FROM_ABI static _Rp __empty_func(const __policy_storage*, __fast_forward<_ArgTypes>...) {
+    std::__throw_bad_function_call();
+  }
+
+  template <class _Fun>
+  _LIBCPP_HIDE_FROM_ABI static _Rp __call_func(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) {
+    _Fun* __func = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value ? &__buf->__small : __buf->__large);
+
+    return std::__invoke_r<_Rp>(*__func, std::forward<_ArgTypes>(__args)...);
+  }
+
 public:
-  _LIBCPP_HIDE_FROM_ABI __policy_func() : __policy_(__policy::__create_empty()) {}
+  _LIBCPP_HIDE_FROM_ABI __policy_func() : __func_(__empty_func), __policy_(__policy::__create_empty()) {}
 
   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()) {
-    typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun;
-
     if (__function::__not_null(__f)) {
-      __invoker_ = __invoker::template __create<_Fun>();
-      __policy_  = __policy::__create<_Fun>();
-      if (__use_small_storage<_Fun>()) {
-        ::new ((void*)&__buf_.__small) _Fun(std::move(__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 _Fun(std::move(__f));
+        __buf_.__large = ::new _Fp(std::move(__f));
       }
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI __policy_func(const __policy_func& __f)
-      : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) {
+      : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) {
     if (__policy_->__clone)
       __buf_.__large = __policy_->__clone(__f.__buf_.__large);
   }
 
   _LIBCPP_HIDE_FROM_ABI __policy_func(__policy_func&& __f)
-      : __buf_(__f.__buf_), __invoker_(__f.__invoker_), __policy_(__f.__policy_) {
+      : __buf_(__f.__buf_), __func_(__f.__func_), __policy_(__f.__policy_) {
     if (__policy_->__destroy) {
-      __f.__policy_  = __policy::__create_empty();
-      __f.__invoker_ = __invoker();
+      __f.__policy_ = __policy::__create_empty();
+      __f.__func_   = {};
     }
   }
 
@@ -539,30 +486,30 @@ class __policy_func<_Rp(_ArgTypes...)> {
   }
 
   _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(__policy_func&& __f) {
-    *this          = nullptr;
-    __buf_         = __f.__buf_;
-    __invoker_     = __f.__invoker_;
-    __policy_      = __f.__policy_;
-    __f.__policy_  = __policy::__create_empty();
-    __f.__invoker_ = __invoker();
+    *this         = nullptr;
+    __buf_        = __f.__buf_;
+    __func_       = __f.__func_;
+    __policy_     = __f.__policy_;
+    __f.__policy_ = __policy::__create_empty();
+    __f.__func_   = {};
     return *this;
   }
 
   _LIBCPP_HIDE_FROM_ABI __policy_func& operator=(nullptr_t) {
     const __policy* __p = __policy_;
     __policy_           = __policy::__create_empty();
-    __invoker_          = __invoker();
+    __func_             = {};
     if (__p->__destroy)
       __p->__destroy(__buf_.__large);
     return *this;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __args) const {
-    return __invoker_.__call_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...);
+    return __func_(std::addressof(__buf_), std::forward<_ArgTypes>(__args)...);
   }
 
   _LIBCPP_HIDE_FROM_ABI void swap(__policy_func& __f) {
-    std::swap(__invoker_, __f.__invoker_);
+    std::swap(__func_, __f.__func_);
     std::swap(__policy_, __f.__policy_);
     std::swap(__buf_, __f.__buf_);
   }


        


More information about the libcxx-commits mailing list