Skip to content

Commit cb723b8

Browse files
committed
[libc++] Implement P0288R9 (move_only_function)
1 parent 5780820 commit cb723b8

Some content is hidden

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

45 files changed

+3475
-49
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ Status
348348
---------------------------------------------------------- -----------------
349349
``__cpp_lib_modules`` ``202207L``
350350
---------------------------------------------------------- -----------------
351-
``__cpp_lib_move_only_function`` *unimplemented*
351+
``__cpp_lib_move_only_function`` ``202110L``
352352
---------------------------------------------------------- -----------------
353353
``__cpp_lib_optional`` ``202110L``
354354
---------------------------------------------------------- -----------------
@@ -498,4 +498,3 @@ Status
498498
---------------------------------------------------------- -----------------
499499
``__cpp_lib_variant`` ``202306L``
500500
========================================================== =================
501-

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Implemented Papers
4545
- ``std::jthread`` and ``<stop_token>`` are not guarded behind ``-fexperimental-library`` anymore
4646
- P2674R1: A trait for implicit lifetime types (`Github <https://github.com/llvm/llvm-project/issues/105259>`__)
4747
- P0429R9: A Standard ``flat_map`` is partially implemented and ``flat_map`` is provided (`Github <https://github.com/llvm/llvm-project/issues/105190>`__)
48+
- P0288R9 - ``move_only_function``
4849

4950
Improvements and New Features
5051
-----------------------------

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

libcxx/include/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ set(files
409409
__functional/is_transparent.h
410410
__functional/mem_fn.h
411411
__functional/mem_fun_ref.h
412+
__functional/move_only_function.h
413+
__functional/move_only_function_common.h
414+
__functional/move_only_function_impl.h
412415
__functional/not_fn.h
413416
__functional/operations.h
414417
__functional/perfect_forward.h

libcxx/include/__configuration/abi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@
124124
// This setting disables the addition of such artificial padding, leading to a more optimal
125125
// representation for several types.
126126
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
127+
// Enable clang::trivial_abi for std::move_only_function
128+
# define _LIBCPP_ABI_SMALL_BUFFER_TRIVIAL_ABI
127129
#elif _LIBCPP_ABI_VERSION == 1
128130
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
129131
// Enable compiling copies of now inline methods into the dylib to support
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: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 _MoveOnlyFunctionTrivialVTable {
31+
using _CallFunc = _ReturnT(_BufferT&, _ArgTypes...);
32+
33+
_CallFunc* __call_;
34+
};
35+
36+
template <class _BufferT, class _ReturnT, class... _ArgTypes>
37+
struct _MoveOnlyFunctionNonTrivialVTable : _MoveOnlyFunctionTrivialVTable<_BufferT, _ReturnT, _ArgTypes...> {
38+
using _DestroyFunc = void(_BufferT&) noexcept;
39+
40+
_DestroyFunc* __destroy_;
41+
};
42+
43+
_LIBCPP_END_NAMESPACE_STD
44+
45+
#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H

0 commit comments

Comments
 (0)