[llvm-branch-commits] [libcxx] [libc++] Implement std::move_only_function (P0288R9) (PR #94670)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 11 17:17:02 PDT 2024


================
@@ -0,0 +1,233 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// This header is unguarded on purpose. This header is an implementation detail of move_only_function.h
+// and generates multiple versions of std::move_only_function
+
+#include <__config>
+#include <__functional/invoke.h>
+#include <__functional/move_only_function_common.h>
+#include <__type_traits/is_trivially_destructible.h>
+#include <__utility/exchange.h>
+#include <__utility/forward.h>
+#include <__utility/in_place.h>
+#include <__utility/move.h>
+#include <__utility/pointer_int_pair.h>
+#include <__utility/small_buffer.h>
+#include <__utility/swap.h>
+#include <cstddef>
+#include <cstring>
+#include <initializer_list>
+#include <new>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+#ifndef _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
+#  error This header should only be included from move_only_function.h
+#endif
+
+#ifndef _LIBCPP_MOVE_ONLY_FUNCTION_CV
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_CV
+#endif
+
+#ifndef _LIBCPP_MOVE_ONLY_FUNCTION_REF
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_REF
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS _LIBCPP_MOVE_ONLY_FUNCTION_CV&
+#else
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS _LIBCPP_MOVE_ONLY_FUNCTION_CV _LIBCPP_MOVE_ONLY_FUNCTION_REF
+#endif
+
+#ifndef _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT false
+#endif
+
+#define _LIBCPP_MOVE_ONLY_FUNCTION_CVREF _LIBCPP_MOVE_ONLY_FUNCTION_CV _LIBCPP_MOVE_ONLY_FUNCTION_REF
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#ifdef _LIBCPP_ABI_MOVE_ONLY_FUNCTION_TRIVIAL_ABI
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_TRIVIAL_ABI [[_Clang::__trivial_abi__]]
+#else
+#  define _LIBCPP_MOVE_ONLY_FUNCTION_TRIVIAL_ABI
+#endif
+
+template <class...>
+class move_only_function;
+
+template <class _ReturnT, class... _ArgTypes>
+class _LIBCPP_MOVE_ONLY_FUNCTION_TRIVIAL_ABI move_only_function<_ReturnT(
+    _ArgTypes...) _LIBCPP_MOVE_ONLY_FUNCTION_CVREF noexcept(_LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT)> {
+private:
+  static constexpr size_t __buffer_size_      = 3 * sizeof(void*);
+  static constexpr size_t __buffer_alignment_ = alignof(void*);
+  using _BufferT                              = __small_buffer<__buffer_size_, __buffer_alignment_>;
+
+  using _TrivialVTable    = _MoveOnlyFunctionTrivialVTable<_BufferT, _ReturnT, _ArgTypes...>;
+  using _NonTrivialVTable = _MoveOnlyFunctionNonTrivialVTable<_BufferT, _ReturnT, _ArgTypes...>;
+
+  template <class _Functor>
+  static constexpr _TrivialVTable __trivial_vtable_ = {
+      .__call_ = [](_BufferT& __buffer, _ArgTypes... __args) noexcept(_LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT) -> _ReturnT {
+        return std::invoke_r<_ReturnT>(
+            static_cast<_Functor _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS>(*__buffer.__get<_Functor>()),
+            std::forward<_ArgTypes>(__args)...);
+      }};
+
+  template <class _Functor>
+  static constexpr _NonTrivialVTable __non_trivial_vtable_{
+      __trivial_vtable_<_Functor>,
+      [](_BufferT& __buffer) noexcept -> void {
+        std::destroy_at(__buffer.__get<_Functor>());
+        __buffer.__dealloc<_Functor>();
+      },
+  };
+
+  template <class _Functor>
+  _LIBCPP_HIDE_FROM_ABI __pointer_bool_pair<const _TrivialVTable*> __get_vptr() {
+    if constexpr (_BufferT::__fits_in_buffer<_Functor> && is_trivially_destructible_v<_Functor>) {
+      return {&__trivial_vtable_<_Functor>, false};
+    } else {
+      return {&__non_trivial_vtable_<_Functor>, true};
+    }
+  }
+
+  template <class _VT>
+  static constexpr bool __is_callable_from = [] {
+    using _DVT = decay_t<_VT>;
+    if (_LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT) {
+      return is_nothrow_invocable_r_v<_ReturnT, _DVT _LIBCPP_MOVE_ONLY_FUNCTION_CVREF, _ArgTypes...> &&
+             is_nothrow_invocable_r_v<_ReturnT, _DVT _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS, _ArgTypes...>;
+    } else {
+      return is_invocable_r_v<_ReturnT, _DVT _LIBCPP_MOVE_ONLY_FUNCTION_CVREF, _ArgTypes...> &&
+             is_invocable_r_v<_ReturnT, _DVT _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS, _ArgTypes...>;
+    }
+  }();
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI void __construct(_Args&&... __args) {
+    static_assert(is_constructible_v<decay_t<_Func>, _Func>);
+
+    using _StoredFunc = decay_t<_Func>;
+    __vtable_         = __get_vptr<_StoredFunc>();
+    __buffer_.__construct<_StoredFunc>(std::forward<_Args>(__args)...);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void __reset() {
+    if (__vtable_.__get_value())
----------------
EricWF wrote:

@philnik777 It seems we're having trouble communicating. I'm happy to meet with you over video chat, hopefully that can clear up any miscommunications.

I promise there is no malice or ill-intent. 

The comment about "killing your darlings" is  honest advice. Perhaps the phrase comes off poorly if you've never heard it before. Here's [a blog post](https://www.masterclass.com/articles/what-does-it-mean-to-kill-your-darlings#what-are-the-origins-of-the-phrase-kill-your-darlings) explaining the saying.

> What Does It Mean to Kill Your Darlings?
Writing is a painful process and most experienced writers will tell you that good writing involves substantial rewriting. An essential part of the rewriting process is combing through your work and cutting out material that isn’t essential. Sometimes this means we have to lose things that we are proud of and attached to. When you edit out material like this, you are killing your darlings.

I've provided a complete & test-passing implementation to compare against. It's the baseline I used for this review. I'm confident my results are repeatable. Please let me know  If can help you reproduce the output I've stated. 





https://github.com/llvm/llvm-project/pull/94670


More information about the llvm-branch-commits mailing list