Skip to content

Commit 7a20300

Browse files
committed
[libc++] Implement P0288R9 (move_only_function)
1 parent 98c61df commit 7a20300

Some content is hidden

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

47 files changed

+3463
-49
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ Status
340340
---------------------------------------------------------- -----------------
341341
``__cpp_lib_mdspan`` ``202207L``
342342
---------------------------------------------------------- -----------------
343-
``__cpp_lib_move_only_function`` *unimplemented*
343+
``__cpp_lib_move_only_function`` ``202110L``
344344
---------------------------------------------------------- -----------------
345345
``__cpp_lib_optional`` ``202110L``
346346
---------------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Implemented Papers
5454
- P2713R1 - Escaping improvements in ``std::format``
5555
- P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant``
5656
- P0019R8 - ``std::atomic_ref``
57+
- P0288R9 - ``move_only_function``
5758

5859
Improvements and New Features
5960
-----------------------------

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>`__","LWG","invoke_r","June 2021","|Complete|","17.0"
2424
"`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"
2525
"","","","","","",""
26-
"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``any_invocable``","October 2021","",""
26+
"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``move_only_function``","October 2021","|Complete|","19.0"
2727
"`P0798R8 <https://wg21.link/P0798R8>`__","LWG","Monadic operations for ``std::optional``","October 2021","|Complete|","14.0"
2828
"`P0849R8 <https://wg21.link/P0849R8>`__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","|Complete|","14.0"
2929
"`P1072R10 <https://wg21.link/P1072R10>`__","LWG","``basic_string::resize_and_overwrite``","October 2021","|Complete|","14.0"

libcxx/include/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ set(files
399399
__functional/is_transparent.h
400400
__functional/mem_fn.h
401401
__functional/mem_fun_ref.h
402+
__functional/move_only_function.h
403+
__functional/move_only_function_common.h
404+
__functional/move_only_function_impl.h
402405
__functional/not_fn.h
403406
__functional/operations.h
404407
__functional/perfect_forward.h

libcxx/include/__configuration/abi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@
9090
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
9191
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
9292
// Dont' add an inline namespace for `std::filesystem`
93-
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
93+
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
94+
// Enable clang::trivial_abi for std::move_only_function
95+
# define _LIBCPP_ABI_SMALL_BUFFER_TRIVIAL_ABI
9496
#elif _LIBCPP_ABI_VERSION == 1
9597
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
9698
// Enable compiling copies of now inline methods into the dylib to support
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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
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 std::function_ref (not voted in yet, expected in C++26).
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+
// NOLINTBEGIN(readability-duplicate-include)
42+
# define _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
43+
44+
# include <__functional/move_only_function_impl.h>
45+
46+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
47+
# include <__functional/move_only_function_impl.h>
48+
49+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
50+
# include <__functional/move_only_function_impl.h>
51+
52+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
53+
# include <__functional/move_only_function_impl.h>
54+
55+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
56+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
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_NOEXCEPT true
64+
# include <__functional/move_only_function_impl.h>
65+
66+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
67+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
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_CV const
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+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &
81+
# include <__functional/move_only_function_impl.h>
82+
83+
# define _LIBCPP_MOVE_ONLY_FUNCTION_NOEXCEPT true
84+
# define _LIBCPP_MOVE_ONLY_FUNCTION_CV const
85+
# define _LIBCPP_MOVE_ONLY_FUNCTION_REF &&
86+
# include <__functional/move_only_function_impl.h>
87+
88+
# undef _LIBCPP_IN_MOVE_ONLY_FUNCTION_H
89+
// NOLINTEND(readability-duplicate-include)
90+
91+
#endif // _LIBCPP_STD_VER > 20
92+
93+
#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
#include <__type_traits/integral_constant.h>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_BEGIN_NAMESPACE_STD
20+
21+
template <class...>
22+
class move_only_function;
23+
24+
template <class>
25+
struct __is_move_only_function : false_type {};
26+
27+
template <class... _Args>
28+
struct __is_move_only_function<move_only_function<_Args...>> : true_type {};
29+
30+
template <class _BufferT, class _ReturnT, class... _ArgTypes>
31+
struct _MoveOnlyFunctionTrivialVTable {
32+
using _CallFunc = _ReturnT(_BufferT&, _ArgTypes...);
33+
34+
_CallFunc* __call_;
35+
};
36+
37+
template <class _BufferT, class _ReturnT, class... _ArgTypes>
38+
struct _MoveOnlyFunctionNonTrivialVTable : _MoveOnlyFunctionTrivialVTable<_BufferT, _ReturnT, _ArgTypes...> {
39+
using _DestroyFunc = void(_BufferT&) noexcept;
40+
41+
_DestroyFunc* __destroy_;
42+
};
43+
44+
_LIBCPP_END_NAMESPACE_STD
45+
46+
#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H

0 commit comments

Comments
 (0)