Skip to content

Commit 7d42ca2

Browse files
committed
[libc++] Implement P0288R9 (move_only_function)
1 parent 8b3a124 commit 7d42ca2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3432
-5
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ Status
356356
---------------------------------------------------------- -----------------
357357
``__cpp_lib_modules`` ``202207L``
358358
---------------------------------------------------------- -----------------
359-
``__cpp_lib_move_only_function`` *unimplemented*
359+
``__cpp_lib_move_only_function`` ``202110L``
360360
---------------------------------------------------------- -----------------
361361
``__cpp_lib_optional`` ``202110L``
362362
---------------------------------------------------------- -----------------
@@ -530,4 +530,3 @@ Status
530530
---------------------------------------------------------- -----------------
531531
``__cpp_lib_variant`` ``202306L``
532532
========================================================== =================
533-

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Implemented Papers
4848
- P2835R7: Expose ``std::atomic_ref``'s object address (`Github <https://llvm.org/PR118377>`__)
4949
- P2944R3: Comparisons for ``reference_wrapper`` (`Github <https://llvm.org/PR105424>`__)
5050
- P3168R2: Give ``std::optional`` Range Support (`Github <https://llvm.org/PR105430>`__)
51+
- P0288R9 - ``move_only_function`` (`Github <https://llvm.org/PR105157>`__)
5152

5253
Improvements and New Features
5354
-----------------------------

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"`P2136R3 <https://wg21.link/P2136R3>`__","invoke_r","2021-06 (Virtual)","|Complete|","17","`#105155 <https://github.com/llvm/llvm-project/issues/105155>`__",""
2424
"`P2166R1 <https://wg21.link/P2166R1>`__","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","2021-06 (Virtual)","|Complete|","13","`#105156 <https://github.com/llvm/llvm-project/issues/105156>`__",""
2525
"","","","","","",""
26-
"`P0288R9 <https://wg21.link/P0288R9>`__","``any_invocable``","2021-10 (Virtual)","","","`#105157 <https://github.com/llvm/llvm-project/issues/105157>`__",""
26+
"`P0288R9 <https://wg21.link/P0288R9>`__","``move_only_function``","2021-10 (Virtual)","|Complete|","22","`#105157 <https://github.com/llvm/llvm-project/issues/105157>`__",""
2727
"`P0798R8 <https://wg21.link/P0798R8>`__","Monadic operations for ``std::optional``","2021-10 (Virtual)","|Complete|","14","`#105158 <https://github.com/llvm/llvm-project/issues/105158>`__",""
2828
"`P0849R8 <https://wg21.link/P0849R8>`__","``auto(x)``: ``DECAY_COPY`` in the language","2021-10 (Virtual)","|Complete|","14","`#105159 <https://github.com/llvm/llvm-project/issues/105159>`__",""
2929
"`P1072R10 <https://wg21.link/P1072R10>`__","``basic_string::resize_and_overwrite``","2021-10 (Virtual)","|Complete|","14","`#105160 <https://github.com/llvm/llvm-project/issues/105160>`__",""

libcxx/include/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@ set(files
427427
__functional/is_transparent.h
428428
__functional/mem_fn.h
429429
__functional/mem_fun_ref.h
430+
__functional/move_only_function.h
431+
__functional/move_only_function_common.h
432+
__functional/move_only_function_impl.h
430433
__functional/not_fn.h
431434
__functional/operations.h
432435
__functional/perfect_forward.h

libcxx/include/__configuration/abi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
8484
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
8585
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
86+
# define _LIBCPP_ABI_SMALL_BUFFER_TRIVIAL_ABI
8687

8788
#elif _LIBCPP_ABI_VERSION == 1
8889
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
10+
#define _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
#if _LIBCPP_STD_VER >= 23 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
19+
20+
// move_only_function design:
21+
//
22+
// move_only_function has a small buffer with a size of `3 * sizeof(void*)` bytes. This buffer can only be used when the
23+
// object that should be stored is trivially relocatable (currently only when it is trivially move constructible and
24+
// trivially destructible). There is also a bool in the lower bits of the vptr stored which is set when the contained
25+
// object is not trivially destructible.
26+
//
27+
// trivially relocatable: It would also be possible to store nothrow_move_constructible types, but that would mean
28+
// that move_only_function itself would not be trivially relocatable anymore. The decision to keep move_only_function
29+
// trivially relocatable was made because we expect move_only_function to be mostly used to store a functor. To only
30+
// forward functors there is C++26's std::function_ref.
31+
//
32+
// buffer size: We did a survey of six implementations from various vendors. Three of them had a buffer size of 24 bytes
33+
// on 64 bit systems. This also allows storing a std::string or std::vector inside the small buffer (once the compiler
34+
// has full support of trivially_relocatable annotations).
35+
//
36+
// trivially-destructible bit: This allows us to keep the overall binary size smaller because we don't have to store
37+
// a pointer to a noop function inside the vtable. It also avoids loading the vtable during destruction, potentially
38+
// resulting in fewer cache misses. The downside is that calling the function now also requires setting the lower bits
39+
// of the pointer to zero, but this is a very fast operation on modern CPUs.
40+
//
41+
// interaction with copyable_function: When converting a copyable_function into a move_only_function we want to avoid
42+
// wrapping the copyable_function inside the move_only_function to avoid a double indirection. Instead, we copy the
43+
// small buffer and use copyable_function's vtable.
44+
45+
// NOLINTBEGIN(readability-duplicate-include)
46+
# define _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
47+
48+
# include <__functional/move_only_function_impl.h>
49+
50+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
51+
# include <__functional/move_only_function_impl.h>
52+
53+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
54+
# include <__functional/move_only_function_impl.h>
55+
56+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
57+
# include <__functional/move_only_function_impl.h>
58+
59+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
60+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
61+
# include <__functional/move_only_function_impl.h>
62+
63+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
64+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
65+
# include <__functional/move_only_function_impl.h>
66+
67+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
68+
# include <__functional/move_only_function_impl.h>
69+
70+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
71+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
72+
# include <__functional/move_only_function_impl.h>
73+
74+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
75+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
76+
# include <__functional/move_only_function_impl.h>
77+
78+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
79+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
80+
# include <__functional/move_only_function_impl.h>
81+
82+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
83+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
84+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
85+
# include <__functional/move_only_function_impl.h>
86+
87+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
88+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
89+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
90+
# include <__functional/move_only_function_impl.h>
91+
92+
# undef _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
93+
// NOLINTEND(readability-duplicate-include)
94+
95+
#endif // _LIBCPP_STD_VER >= 23 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
96+
97+
#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
10+
#define _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
_LIBCPP_BEGIN_NAMESPACE_STD
19+
20+
template <class...>
21+
class move_only_function;
22+
23+
template <class>
24+
inline constexpr bool __is_move_only_function_v = false;
25+
26+
template <class... _Args>
27+
inline constexpr bool __is_move_only_function_v<move_only_function<_Args...>> = true;
28+
29+
template <class _BufferT, class _ReturnT, class... _ArgTypes>
30+
struct _MoveOnlyFunctionVTable {
31+
using _CallFunc = _ReturnT(_BufferT&, _ArgTypes...);
32+
using _DestroyFunc = void(_BufferT&) noexcept;
33+
34+
_CallFunc* __call_;
35+
_DestroyFunc* __destroy_;
36+
};
37+
38+
_LIBCPP_END_NAMESPACE_STD
39+
40+
#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H

0 commit comments

Comments
 (0)