[libcxx-commits] [libcxx] [libc++] Implement std::move_only_function (P0288R9) (PR #94670)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jun 6 12:36:50 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
- [libc++] Add __pointer_int_pair
- [libc++] Implement P0288R9 (move_only_function)
---
Patch is 217.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/94670.diff
51 Files Affected:
- (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1)
- (modified) libcxx/docs/ReleaseNotes/19.rst (+1)
- (modified) libcxx/docs/Status/Cxx23Papers.csv (+1-1)
- (modified) libcxx/include/CMakeLists.txt (+4)
- (modified) libcxx/include/__configuration/abi.h (+3-1)
- (added) libcxx/include/__functional/move_only_function.h (+93)
- (added) libcxx/include/__functional/move_only_function_common.h (+46)
- (added) libcxx/include/__functional/move_only_function_impl.h (+233)
- (modified) libcxx/include/__std_clang_module (+1)
- (added) libcxx/include/__utility/pointer_int_pair.h (+157)
- (modified) libcxx/include/functional (+1)
- (modified) libcxx/include/module.modulemap (+4)
- (modified) libcxx/include/version (+1-1)
- (modified) libcxx/modules/std.cppm.in (+1)
- (added) libcxx/test/libcxx/private_headers.verify.cpp (+717)
- (added) libcxx/test/libcxx/utilities/function.objects/func.wrap/func.wrap.move/assert.engaged.cpp (+20)
- (added) libcxx/test/libcxx/utilities/pointer_int_pair.pass.cpp (+37)
- (added) libcxx/test/libcxx/utilities/pointer_int_pair/assert.constructor.pass.cpp (+44)
- (added) libcxx/test/libcxx/utilities/pointer_int_pair/constinit.verify.cpp (+21)
- (added) libcxx/test/libcxx/utilities/pointer_int_pair/pointer_int_pair.pass.cpp (+104)
- (added) libcxx/test/libcxx/utilities/pointer_int_pair/static_asserts.verify.cpp (+23)
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp (+10-22)
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+10-22)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/assignment/functor.pass.cpp (+84)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/assignment/move.pass.cpp (+91)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/assignment/move_other.pass.cpp (+62)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/assignment/nullptr.pass.cpp (+73)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/lvalue.pass.cpp (+102)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/lvalue_const.pass.cpp (+118)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/lvalue_const_noexcept.pass.cpp (+113)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/lvalue_noexcept.pass.cpp (+102)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/normal.pass.cpp (+106)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/normal_const.pass.cpp (+112)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/normal_const_noexcept.pass.cpp (+112)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/normal_noexcept.pass.cpp (+106)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/rvalue.pass.cpp (+104)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/rvalue_const.pass.cpp (+107)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/rvalue_const_noexcept.pass.cpp (+107)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/call/rvalue_noexcept.pass.cpp (+104)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/common.h (+80)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/default.pass.cpp (+28)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/functor.pass.cpp (+115)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/in_place.pass.cpp (+46)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/in_place_init_list.pass.cpp (+46)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/move.pass.cpp (+106)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/move_other.pass.cpp (+44)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/ctors/nullptr.pass.cpp (+28)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/swap.adl.pass.cpp (+73)
- (added) libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.move/swap.member.pass.cpp (+73)
- (modified) libcxx/test/support/type_algorithms.h (+36)
- (modified) libcxx/utils/generate_feature_test_macro_components.py (-1)
``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 0297068785e8b..69296fdc98ae2 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -340,7 +340,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_mdspan`` ``202207L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_move_only_function`` *unimplemented*
+ ``__cpp_lib_move_only_function`` ``202110L``
---------------------------------------------------------- -----------------
``__cpp_lib_optional`` ``202110L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 0bc343acd281c..9e142d2bdda92 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -54,6 +54,7 @@ Implemented Papers
- P2713R1 - Escaping improvements in ``std::format``
- P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant``
- P0019R8 - ``std::atomic_ref``
+- P0288R9 - ``move_only_function``
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 01387a404f5d6..b5da5cad5f060 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -23,7 +23,7 @@
"`P2136R3 <https://wg21.link/P2136R3>`__","LWG","invoke_r","June 2021","|Complete|","17.0"
"`P2166R1 <https://wg21.link/P2166R1>`__","LWG","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","June 2021","|Complete|","13.0"
"","","","","","",""
-"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``any_invocable``","October 2021","",""
+"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``move_only_function``","October 2021","|Complete|","19.0"
"`P0798R8 <https://wg21.link/P0798R8>`__","LWG","Monadic operations for ``std::optional``","October 2021","|Complete|","14.0"
"`P0849R8 <https://wg21.link/P0849R8>`__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","|Complete|","14.0"
"`P1072R10 <https://wg21.link/P1072R10>`__","LWG","``basic_string::resize_and_overwrite``","October 2021","|Complete|","14.0"
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cfe1f44777bca..17573d3e67de8 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -399,6 +399,9 @@ set(files
__functional/is_transparent.h
__functional/mem_fn.h
__functional/mem_fun_ref.h
+ __functional/move_only_function.h
+ __functional/move_only_function_common.h
+ __functional/move_only_function_impl.h
__functional/not_fn.h
__functional/operations.h
__functional/perfect_forward.h
@@ -857,6 +860,7 @@ set(files
__utility/no_destroy.h
__utility/pair.h
__utility/piecewise_construct.h
+ __utility/pointer_int_pair.h
__utility/priority_tag.h
__utility/private_constructor_tag.h
__utility/rel_ops.h
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 17aceb042f524..31c23ff7fa889 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -90,7 +90,9 @@
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
// Dont' add an inline namespace for `std::filesystem`
-# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
+# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
+// Enable clang::trivial_abi for std::move_only_function
+# define _LIBCPP_ABI_SMALL_BUFFER_TRIVIAL_ABI
#elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
diff --git a/libcxx/include/__functional/move_only_function.h b/libcxx/include/__functional/move_only_function.h
new file mode 100644
index 0000000000000..4cda276e37d7f
--- /dev/null
+++ b/libcxx/include/__functional/move_only_function.h
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
+#define _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER >= 23
+
+// move_only_function design:
+//
+// move_only_function has a small buffer with a size of `3 * sizeof(void*)` bytes. This buffer can only be used when the
+// object that should be stored is trivially relocatable (currently only when it is trivially move constructible and
+// trivially destructible). There is also a bool in the lower bits of the vptr stored which is set when the contained
+// object is not trivially destructible.
+//
+// trivially relocatable: It would also be possible to store nothrow_move_constructible types, but that would mean
+// that move_only_function itself would not be trivially relocatable anymore. The decision to keep move_only_function
+// trivially relocatable was made because we expect move_only_function to be mostly used to store a functor. To only
+// forward functors there is std::function_ref (not voted in yet, expected in C++26).
+//
+// buffer size: We did a survey of six implementations from various vendors. Three of them had a buffer size of 24 bytes
+// on 64 bit systems. This also allows storing a std::string or std::vector inside the small buffer (once the compiler
+// has full support of trivially_relocatable annotations).
+//
+// trivially-destructible bit: This allows us to keep the overall binary size smaller because we don't have to store
+// a pointer to a noop function inside the vtable. It also avoids loading the vtable during destruction, potentially
+// resulting in fewer cache misses. The downside is that calling the function now also requires setting the lower bits
+// of the pointer to zero, but this is a very fast operation on modern CPUs.
+
+// NOLINTBEGIN(readability-duplicate-include)
+# define _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
+
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
+# include <__functional/move_only_function_impl.h>
+
+# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
+# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
+# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
+# include <__functional/move_only_function_impl.h>
+
+# undef _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
+// NOLINTEND(readability-duplicate-include)
+
+#endif // _LIBCPP_STD_VER > 20
+
+#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
diff --git a/libcxx/include/__functional/move_only_function_common.h b/libcxx/include/__functional/move_only_function_common.h
new file mode 100644
index 0000000000000..45978bfc91aad
--- /dev/null
+++ b/libcxx/include/__functional/move_only_function_common.h
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
+#define _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
+
+#include <__config>
+#include <__type_traits/integral_constant.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class...>
+class move_only_function;
+
+template <class>
+struct __is_move_only_function : false_type {};
+
+template <class... _Args>
+struct __is_move_only_function<move_only_function<_Args...>> : true_type {};
+
+template <class _BufferT, class _ReturnT, class... _ArgTypes>
+struct _MoveOnlyFunctionTrivialVTable {
+ using _CallFunc = _ReturnT(_BufferT&, _ArgTypes...);
+
+ _CallFunc* __call_;
+};
+
+template <class _BufferT, class _ReturnT, class... _ArgTypes>
+struct _MoveOnlyFunctionNonTrivialVTable : _MoveOnlyFunctionTrivialVTable<_BufferT, _ReturnT, _ArgTypes...> {
+ using _DestroyFunc = void(_BufferT&) noexcept;
+
+ _DestroyFunc* __destroy_;
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
diff --git a/libcxx/include/__functional/move_only_function_impl.h b/libcxx/include/__functional/move_only_function_impl.h
new file mode 100644
index 0000000000000..9d006ea346162
--- /dev/null
+++ b/libcxx/include/__functional/move_only_function_impl.h
@@ -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())
+ static_cast<const _NonTrivialVTable*>(__vtable_.__get_ptr())->__destroy_(__buffer_);
+ __vtable_ = {};
+ }
+
+public:
+ using result_type = _ReturnT;
+
+ // [func.wrap.move.ctor]
+ move_only_function() noexcept = default;
+ _LIBCPP_HIDE_FROM_ABI move_only_function(nullptr_t) noexcept {}
+ _LIBCPP_HIDE_FROM_ABI move_only_function(move_only_function&& __other) noexcept
+ : __vtable_(__other.__vtable_), __buffer_(std::move(__other.__buffer_)) {
+ __other.__vtable_ = {};
+ }
+
+ template <class _Func>
+ requires(!is_same_v<remove_cvref_t<_Func>, move_only_function> && !__is_inplace_type<_Func>::value &&
+ __is_callable_from<_Func>)
+ _LIBCPP_HIDE_FROM_ABI move_only_function(_Func&& __func) noexcept {
+ using _StoredFunc = decay_t<_Func>;
+
+ if constexpr ((is_pointer_v<_StoredFunc> && is_function_v<remove_pointer_t<_StoredFunc>>) ||
+ is_member_function_pointer_v<_StoredFunc>) {
+ if (__func != nullptr) {
+ __vtable_ = __get_vptr<_StoredFunc>();
+ static_assert(_BufferT::__fits_in_buffer<_StoredFunc>);
+ __buffer_.__construct<_StoredFunc>(std::forward<_Func>(__func));
+ }
+ } else if constexpr (__is_move_only_function<_StoredFunc>::value) {
+ if (__func) {
+ __vtable_ = std::exchange(__func.__vtable_, {});
+ __buffer_ = std::move(__func.__buffer_);
+ }
+ } else {
+ __construct<_Func>(std::forward<_Func>(__func));
+ }
+ }
+
+ template <class _Func, class... _Args>
+ requires is_constructible_v<decay_t<_Func>, _Args...> && __is_callable_from<_Func>
+ _LIBCPP_HIDE_FROM_ABI explicit move_only_function(in_place_type_t<_Func>, _Args&&... __args) {
+ static_assert(is_same_v<decay_t<_Func>, _Func>);
+ __construct<_Func>(std::forward<_Args>(__args)...);
+ }
+
+ template <class _Func, class _InitListType, class... _Args>
+ requires is_constructible_v<decay_t<_Func>, initializer_list<_InitListType>&, _Args...> && __is_callable_from<_Func>
+ _LIBCPP_HIDE_FROM_ABI explicit move_only_function(
+ in_place_type_t<_Func>, initializer_list<_InitListType> __il, _Args&&... __args) {
+ static_assert(is_same_v<decay_t<_Func>, _Func>);
+ __construct<_Func>(__il, std::forward<_Args>(__args)...);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI move_only_function& operator=(move_only_function&& __other) noexcept {
+ move_only_function(std::move(__other)).swap(*this);
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI move_only_function& operator=(nullptr_t) noexcept {
+ __reset();
+ return *this;
+ }
+
+ template <class _Func>
+ requires(!is_same_v<remove_cvref_t<_Func>, move_only_function> && !__is_inplace_type<_Func>::value &&
+ __is_callable_from<_Func>)
+ _LIBCPP_HIDE_FROM_ABI move_only_function& operator=(_Func&& __func) {
+ move_only_function(std::forward<_Func>(__func)).swap(*this);
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI ~move_only_function() { __reset(); }
+
+ // [func.wrap.move.inv]
+ _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __vtable_.__get_ptr() != nullptr; }
+
+ _LIBCPP_HIDE_FROM_ABI _ReturnT operator()(_ArgTypes... __args) _LIBCPP_MOVE_ONLY_FUNCTION_CVREF
+ noexcept(_LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT) {
+ _LIBCPP_ASSERT(static_cast<bool>(*this), "Tried to call a disengaged move_only_function");
+ const auto __call = static_cast<_ReturnT (*)(_BufferT&, _ArgTypes...)>(__vtable_.__get_ptr()->__call_);
+ return __call(__buffer_, std::forward<_ArgTypes>(__args)...);
+ }
+
+ // [func.wrap.move.util]
+ _LIBCPP_HIDE_FROM_ABI void swap(move_only_function& __other) noexcept {
+ std::swap(__vtable_, __other.__vtable_);
+ std::swap(__buffer_, __other.__buffer_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend void swap(move_only_function& __lhs, move_only_function& __rhs) noexcept {
+ __lhs.swap(__rhs);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator==(const move_only_function& __func, nullptr_t) noexcept { return !__func; }
+
+private:
+ __pointer_bool_pair<const _TrivialVTable*> __vtable_ = {};
+ mutable _BufferT __buffer_;
+
+ template <class...>
+ friend class move_only_function;
+};
+
+#undef _LIBCPP_MOVE_ONLY_FUNCTION_CV
+#undef _LIBCPP_MOVE_ONLY_FUNCTION_REF
+#undef _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT
+#undef _LIBCPP_MOVE_ONLY_FUNCTION_INVOKE_QUALS
+#undef _LIBCPP_MOVE_ONLY_FUNCTION_CVREF
+
+_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__std_clang_module b/libcxx/include/__std_clang_module
index 18d6ce6b46c1f..e48a3e876ef84 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -136,6 +136,7 @@
#include <mdspan>
#include <memory>
#include <memory_resource>
+#include <module.modulemap.in>
#include <mutex>
#include <new>
#include <numbers>
diff --git a/libcxx/include/__utility/pointer_int_pair.h b/libcxx/include/__utility/pointer_int_pair.h
new file mode 100644
index 0000000000000..5a08b74686166
--- /dev/null
+++ b/libcxx/include/__utility/pointer_int_pair.h
@@ -0,0 +1,157 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Except...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/94670
More information about the libcxx-commits
mailing list