Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[libc++] Implement std::move_only_function (P0288R9) #94670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: users/philnik777/spr/add_pointer_int_pair
Choose a base branch
Loading
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions 3 libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_modules`` ``202207L``
---------------------------------------------------------- -----------------
``__cpp_lib_move_only_function`` *unimplemented*
``__cpp_lib_move_only_function`` ``202110L``
---------------------------------------------------------- -----------------
``__cpp_lib_optional`` ``202110L``
---------------------------------------------------------- -----------------
Expand Down Expand Up @@ -498,4 +498,3 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================

1 change: 1 addition & 0 deletions 1 libcxx/docs/ReleaseNotes/20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Implemented Papers
- ``std::jthread`` and ``<stop_token>`` are not guarded behind ``-fexperimental-library`` anymore
- P2674R1: A trait for implicit lifetime types (`Github <https://github.com/llvm/llvm-project/issues/105259>`__)
- P0429R9: A Standard ``flat_map`` is partially implemented and ``flat_map`` is provided (`Github <https://github.com/llvm/llvm-project/issues/105190>`__)
- P0288R9 - ``move_only_function``

Improvements and New Features
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion 2 libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"`P2136R3 <https://wg21.link/P2136R3>`__","invoke_r","2021-06 (Virtual)","|Complete|","17.0",""
"`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",""
"","","","","",""
"`P0288R9 <https://wg21.link/P0288R9>`__","``any_invocable``","2021-10 (Virtual)","","",""
"`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``move_only_function``","October 2021","|Complete|","20.0"
"`P0798R8 <https://wg21.link/P0798R8>`__","Monadic operations for ``std::optional``","2021-10 (Virtual)","|Complete|","14.0",""
"`P0849R8 <https://wg21.link/P0849R8>`__","``auto(x)``: ``DECAY_COPY`` in the language","2021-10 (Virtual)","|Complete|","14.0",""
"`P1072R10 <https://wg21.link/P1072R10>`__","``basic_string::resize_and_overwrite``","2021-10 (Virtual)","|Complete|","14.0",""
Expand Down
4 changes: 4 additions & 0 deletions 4 libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,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
Expand Down Expand Up @@ -877,6 +880,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
Expand Down
2 changes: 2 additions & 0 deletions 2 libcxx/include/__configuration/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
// This setting disables the addition of such artificial padding, leading to a more optimal
// representation for several types.
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
// 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
Expand Down
97 changes: 97 additions & 0 deletions 97 libcxx/include/__functional/move_only_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===----------------------------------------------------------------------===//
//
// 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 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)

// move_only_function design:
philnik777 marked this conversation as resolved.
Show resolved Hide resolved
//
// 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 C++26's std::function_ref.
//
// 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.
philnik777 marked this conversation as resolved.
Show resolved Hide resolved
//
// interaction with copyable_function: When converting a copyable_function into a move_only_function we want to avoid
// wrapping the copyable_function inside the move_only_function to avoid a double indirection. Instead, we copy the
// small buffer and use copyable_function's vtable.

// 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 >= 23 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)

#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_H
45 changes: 45 additions & 0 deletions 45 libcxx/include/__functional/move_only_function_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//===----------------------------------------------------------------------===//
//
// 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>

#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>
inline constexpr bool __is_move_only_function_v = false;

template <class... _Args>
inline constexpr bool __is_move_only_function_v<move_only_function<_Args...>> = true;

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...> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to instantiate this type with _ReturnT or _ArgTypes....

That's alot of template bloat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate? I don't see how we can have the vtable function pointer without the template arguments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You either don't need the inheritance, or you don't need to give the "destruct" base class all the arguments, you only need that for the call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call function pointer is in the base class though. I always want the call pointer and only sometimes the destructor pointer.

using _DestroyFunc = void(_BufferT&) noexcept;

_DestroyFunc* __destroy_;
};

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___FUNCTIONAL_MOVE_ONLY_FUNCTION_COMMON_H
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.