From 6172b5e50f5f00df4861720fde6b4df12393ce3a Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Wed, 11 Jun 2025 19:57:40 -0700 Subject: [PATCH] add move_only_function docs --- doc/compat/move_only_function.adoc | 252 +++++++++++++++++++++++++++++ doc/compat/reference.adoc | 1 + 2 files changed, 253 insertions(+) create mode 100644 doc/compat/move_only_function.adoc diff --git a/doc/compat/move_only_function.adoc b/doc/compat/move_only_function.adoc new file mode 100644 index 0000000..6a180e2 --- /dev/null +++ b/doc/compat/move_only_function.adoc @@ -0,0 +1,252 @@ +//// +Copyright 2025 Christian Mazakas +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#move_only_function] +# +:idprefix: ref_move_only_function_ + +## Description + +The header `` implements the {cpp}23 class https://en.cppreference.com/w/cpp/utility/functional/move_only_function.html[std::move_only_function]. + +`move_only_function` is a polymorphic wrapper that stores and manages a https://en.cppreference.com/w/cpp/named_req/Callable[Callable], only requiring that the type supports move construction and move assignment. +This is in contrast to the commonly used `std::function` which requires copyability of the underlying managed object. + +`move_only_function` supports every combination of `const`, `noexcept` and reference qualification (none, `&`, `&&`). + +## Example + +```cpp +struct moveonly +{ + std::unique_ptr p_ = std::make_unique( 1234 ); + auto operator()( int x ) noexcept { return *p_ + x; } +}; + +boost::compat::move_only_function f( moveonly{} ); +std::cout << f( 4321 ) << std::endl; +``` + +## Synopsis + +```cpp +namespace boost { +namespace compat { + +template +class move_only_function; + +template< class T > +struct in_place_type_t { explicit in_place_type_t() = default; }; + +template +class move_only_function +{ + move_only_function() noexcept; + move_only_function( std::nullptr_t ) noexcept; + + template + move_only_function( F&& f ); + + template + explicit move_only_function( in_place_type_t, CArgs&& ... args ); + + template + explicit move_only_function( in_place_type_t, + std::initializer_list il, CArgs&& ... args ); + + move_only_function( move_only_function const& ) = delete; + move_only_function( move_only_function&& ) = default; + + ~move_only_function() = default; + + move_only_function& operator=( move_only_function&& rhs ); + move_only_function& operator=( std::nullptr_t ) noexcept; + template move_only_function& operator=( F&& f ); + + friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept; + friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept; + + void swap( move_only_function& rhs ) noexcept; + friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept; + + explicit operator bool() const noexcept; + + R operator()( Args... args ) /* cv */ /* ref */ noexcept( /* noex */ ); +}; + +} // namespace compat +} // namespace boost + +``` + +## Constructors + +### Default Constructor + +```cpp +move_only_function() noexcept; +``` + +[horizontal] +Effects:: +Constructs an empty `move_only_function` which manages no object. + +### Null Constructor + +```cpp +move_only_function( std::nullptr_t ) noexcept; +``` + +[horizontal] +Effects:: +Explicitly constructs an empty `move_only_function` using a nullptr value. Equivalent to default construction. + +### Object Constructor + +```cpp +template +move_only_function( F&& f ); +``` + +[horizontal] +Effects:;; Given `using VT = decay_t`, directly constructs an instance of `VT` using `forward(f)` and stores it as the target object. + ++ +If `F` is an empty function pointer, pointer-to-member or specialization of `move_only_function` then the constructed `move_only_function` is empty. +Constraints:;; ++ +-- +* `remove_cv_ref` is not the same type as `move_only_function` +* `remove_cv_ref` is not a specialization of `in_place_type_t` +* `VT` must be callable with the provided cvref qualifiers and the provided argument types +-- + +### In-Place Constructor + +```cpp +template +explicit move_only_function( in_place_type_t, CArgs&& ... args ); +``` + +[horizontal] +Effects:;; Constructs an object of type `T` using the provided args directly, storing it as the target object. +Constraints:;; ++ +-- +* `is_constructible_v` must be true +* `T` must be callable with the provided cvref qualifiers and the provided argument types +-- + +### List In-Place Constructor + +```cpp +template +explicit move_only_function( in_place_type_t, + std::initializer_list il, CArgs&& ... args ); +``` + +[horizontal] +Effects:;; Constructs an object of type `T` using the provided initializer_list and args directly, storing it as the target Callable. +Constraints:;; ++ +-- +* `is_constructible_v&, CArgs...>` must be true +* `T` must be callable with the provided cvref qualifiers and the provided argument types +-- + +### Move Constructor + +```cpp +move_only_function( move_only_function&& f ) = default; +``` + +[horizontal] +Effects:: +Tranfers ownership of the object managed by `f` to `*this`. After this operation completes, `f` is empty and manages no object. + +## Assignment + +### Move Assignment + +```cpp +move_only_function& operator=( move_only_function&& rhs ); +``` + +[horizontal] +Effects:;; Releases the currently managed object and takes ownership of the object managed by `rhs`, if applicable. +`rhs` is empty after move. + +### Null Assigment + +```cpp +move_only_function& operator=( std::nullptr_t ) noexcept; +``` + +[horizontal] +Effects:;; Releases the currently managed object, if applicable. + +### Callable Assignment + +```cpp +template move_only_function& operator=( F&& f ); +``` + +[horizontal] +Effects:;; Releases the currently managed object and then does the equivalent of: `move_only_function(std::forward(f)).swap(*this)`. + +## Utility + +### Null Equality + +```cpp +friend bool operator==( move_only_function const& fn, std::nullptr_t ) noexcept; +friend bool operator!=( move_only_function const& fn, std::nullptr_t ) noexcept; +``` + +[horizontal] +Effects:;; Returns whether or not `fn` contains a target object. + +### Swap + +```cpp +void swap( move_only_function& rhs ) noexcept; +friend void swap( move_only_function& lhs, move_only_function& rhs ) noexcept; +``` + +[horizontal] +Effects:;; Exchanges the managed objects. + +## Invocation + +### Boolean Conversion + +```cpp +explicit operator bool() const noexcept; +``` + +[horizontal] +Effects:;; Returns `true` if `*this` is managing an object, or `false` if `*this` is empty. + +### Call Operator + +```cpp +R operator()( Args... args ) /* cv */ /* ref */ noexcept( /* noex */ ); +``` + +[horizontal] +Preconditions:;; `*this` currently manages an object. +Effects:;; Invokes the underlying target object. Equivalent to: ++ +-- +```cpp +return INVOKE(static_cast(f), std::forward(args)...); +``` + +where `f` is the target object, and _inv-quals_ is defined by the standard: + +* If _ref_ is empty, let _inv-quals_ be _cv&_, +* otherwise, let _inv-quals_ be _cv ref_. +-- diff --git a/doc/compat/reference.adoc b/doc/compat/reference.adoc index 114d916..a620c05 100644 --- a/doc/compat/reference.adoc +++ b/doc/compat/reference.adoc @@ -7,6 +7,7 @@ https://www.boost.org/LICENSE_1_0.txt include::bind_back.adoc[] include::bind_front.adoc[] include::function_ref.adoc[] +include::move_only_function.adoc[] include::integer_sequence.adoc[] include::invoke.adoc[] include::latch.adoc[]