diff options
Diffstat (limited to 'pw_function/docs.rst')
-rw-r--r-- | pw_function/docs.rst | 179 |
1 files changed, 103 insertions, 76 deletions
diff --git a/pw_function/docs.rst b/pw_function/docs.rst index 18041ef51..b8d9b7ed8 100644 --- a/pw_function/docs.rst +++ b/pw_function/docs.rst @@ -23,36 +23,36 @@ the stored callable. .. code-block:: c++ - int Add(int a, int b) { return a + b; } + int Add(int a, int b) { return a + b; } - // Construct a Function object from a function pointer. - pw::Function<int(int, int)> add_function(Add); + // Construct a Function object from a function pointer. + pw::Function<int(int, int)> add_function(Add); - // Invoke the function object. - int result = add_function(3, 5); - EXPECT_EQ(result, 8); + // Invoke the function object. + int result = add_function(3, 5); + EXPECT_EQ(result, 8); - // Construct a function from a lambda. - pw::Function<int(int)> negate([](int value) { return -value; }); - EXPECT_EQ(negate(27), -27); + // Construct a function from a lambda. + pw::Function<int(int)> negate([](int value) { return -value; }); + EXPECT_EQ(negate(27), -27); Functions are nullable. Invoking a null function triggers a runtime assert. .. code-block:: c++ - // A function initialized without a callable is implicitly null. - pw::Function<void()> null_function; + // A function initialized without a callable is implicitly null. + pw::Function<void()> null_function; - // Null functions may also be explicitly created or set. - pw::Function<void()> explicit_null_function(nullptr); + // Null functions may also be explicitly created or set. + pw::Function<void()> explicit_null_function(nullptr); - pw::Function<void()> function([]() {}); // Valid (non-null) function. - function = nullptr; // Set to null, clearing the stored callable. + pw::Function<void()> function([]() {}); // Valid (non-null) function. + function = nullptr; // Set to null, clearing the stored callable. - // Functions are comparable to nullptr. - if (function != nullptr) { - function(); - } + // Functions are comparable to nullptr. + if (function != nullptr) { + function(); + } :cpp:type:`pw::Function`'s default constructor is ``constexpr``, so default-constructed functions may be used in classes with ``constexpr`` @@ -60,23 +60,22 @@ constructors and in ``constinit`` expressions. .. code-block:: c++ - class MyClass { - public: - // Default construction of a pw::Function is constexpr. - constexpr MyClass() { ... } + class MyClass { + public: + // Default construction of a pw::Function is constexpr. + constexpr MyClass() { ... } - pw::Function<void(int)> my_function; - }; + pw::Function<void(int)> my_function; + }; - // pw::Function and classes that use it may be constant initialized. - constinit MyClass instance; + // pw::Function and classes that use it may be constant initialized. + constinit MyClass instance; Storage ======= By default, a ``Function`` stores its callable inline within the object. The -inline storage size defaults to the size of two pointers, but is configurable -through the build system. The size of a ``Function`` object is equivalent to its -inline storage size. +inline storage size defaults to the size of one pointer, but is configurable +through the build system. The :cpp:type:`pw::InlineFunction` alias is similar to :cpp:type:`pw::Function`, but is always inlined. That is, even if dynamic allocation is enabled for @@ -88,36 +87,41 @@ is a compile-time error unless dynamic allocation is enabled. .. admonition:: Inline storage size - The default inline size of two pointers is sufficient to store most common - callable objects, including function pointers, simple non-capturing and - capturing lambdas, and lightweight custom classes. + The default inline size of one pointer is sufficient to store most common + callable objects, including function pointers, simple non-capturing and + capturing lambdas, and lightweight custom classes. .. code-block:: c++ - // The lambda is moved into the function's internal storage. - pw::Function<int(int, int)> subtract([](int a, int b) { return a - b; }); + // The lambda is moved into the function's internal storage. + pw::Function<int(int, int)> subtract([](int a, int b) { return a - b; }); - // Functions can be also be constructed from custom classes that implement - // operator(). This particular object is large (8 ints of space). - class MyCallable { - public: - int operator()(int value); + // Functions can be also be constructed from custom classes that implement + // operator(). This particular object is large (8 ints of space). + class MyCallable { + public: + int operator()(int value); - private: - int data_[8]; - }; + private: + int data_[8]; + }; - // Compiler error: sizeof(MyCallable) exceeds function's inline storage size. - pw::Function<int(int)> function((MyCallable())); + // Compiler error: sizeof(MyCallable) exceeds function's inline storage size. + pw::Function<int(int)> function((MyCallable())); .. admonition:: Dynamic allocation - When ``PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION`` is enabled, a ``Function`` - will use dynamic allocation to store callables that exceed the inline size. - When it is enabled but a compile-time check for the inlining is still required - ``pw::InlineFunction`` can be used. + When ``PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION`` is enabled, a ``Function`` + will use dynamic allocation to store callables that exceed the inline size. + An Allocator type can be optionally supplied as a template argument. The + default Allocator type can also be changed by overriding + ``PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE`` (the ``value_type`` of the Allocator + is irrelevant, since it must support rebinding). When dynamic allocation is + enabled but a compile-time check for the inlining is still required + ``pw::InlineFunction`` can be used. .. warning:: + If ``PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION`` is enabled then attempts to cast from `:cpp:type:`pw::InlineFunction` to a regular :cpp:type:`pw::Function` will **ALWAYS** allocate memory. @@ -132,6 +136,7 @@ Reference .. doxygentypedef:: pw::InlineFunction .. doxygentypedef:: pw::Callback .. doxygentypedef:: pw::InlineCallback +.. doxygenfunction:: pw::bind_member ``pw::Function`` as a function parameter ======================================== @@ -140,12 +145,12 @@ place of a function pointer or equivalent callable. .. code-block:: c++ - // Before: - void DoTheThing(int arg, void (*callback)(int result)); + // Before: + void DoTheThing(int arg, void (*callback)(int result)); - // After. Note that it is possible to have parameter names within the function - // signature template for clarity. - void DoTheThing(int arg, const pw::Function<void(int result)>& callback); + // After. Note that it is possible to have parameter names within the function + // signature template for clarity. + void DoTheThing(int arg, const pw::Function<void(int result)>& callback); :cpp:type:`pw::Function` is movable, but not copyable, so APIs must accept :cpp:type:`pw::Function` objects either by const reference (``const @@ -157,29 +162,30 @@ should be passed as an rvalue reference and moved into a .. code-block:: c++ - // This function calls a pw::Function but doesn't store it, so it takes a - // const reference. - void CallTheCallback(const pw::Function<void(int)>& callback) { - callback(123); - } + // This function calls a pw::Function but doesn't store it, so it takes a + // const reference. + void CallTheCallback(const pw::Function<void(int)>& callback) { + callback(123); + } - // This function move-assigns a pw::Function to another variable, so it takes - // an rvalue reference. - void StoreTheCallback(pw::Function<void(int)>&& callback) { - stored_callback_ = std::move(callback); - } + // This function move-assigns a pw::Function to another variable, so it takes + // an rvalue reference. + void StoreTheCallback(pw::Function<void(int)>&& callback) { + stored_callback_ = std::move(callback); + } .. admonition:: Rules of thumb for passing a :cpp:type:`pw::Function` to a function * **Pass by value**: Never. - This results in unnecessary :cpp:type:`pw::Function` instances and move operations. + * **Pass by const reference** (``const pw::Function&``): When the :cpp:type:`pw::Function` is only invoked. When a :cpp:type:`pw::Function` is called or inspected, but not moved, take a const reference to avoid copies and support temporaries. + * **Pass by rvalue reference** (``pw::Function&&``): When the :cpp:type:`pw::Function` is moved. @@ -190,6 +196,7 @@ should be passed as an rvalue reference and moved into a :cpp:type:`pw::Function` variable, which makes the transfer of ownership explicit. It is possible to move-assign from an lvalue reference, but this fails to make it obvious to the caller that the object is no longer valid. + * **Pass by non-const reference** (``pw::Function&``): Rarely, when modifying a variable. @@ -206,11 +213,11 @@ the callable object. There is no need to create an intermediate .. code-block:: c++ - // Implicitly creates a pw::Function from a capturing lambda and calls it. - CallTheCallback([this](int result) { result_ = result; }); + // Implicitly creates a pw::Function from a capturing lambda and calls it. + CallTheCallback([this](int result) { result_ = result; }); - // Implicitly creates a pw::Function from a capturing lambda and stores it. - StoreTheCallback([this](int result) { result_ = result; }); + // Implicitly creates a pw::Function from a capturing lambda and stores it. + StoreTheCallback([this](int result) { result_ = result; }); When working with an existing :cpp:type:`pw::Function` variable, the variable can be passed directly to functions that take a const reference. If the function @@ -219,11 +226,11 @@ takes ownership of the :cpp:type:`pw::Function`, move the .. code-block:: c++ - // Accepts the pw::Function by const reference. - CallTheCallback(my_function_); + // Accepts the pw::Function by const reference. + CallTheCallback(my_function_); - // Takes ownership of the pw::Function. - void StoreTheCallback(std::move(my_function)); + // Takes ownership of the pw::Function. + void StoreTheCallback(std::move(my_function)); ``pw::Callback`` for one-shot functions ======================================= @@ -235,6 +242,11 @@ nullptr. Invoking ``pw::Function`` from a C-style API ============================================ +.. _trampoline layers: https://en.wikipedia.org/wiki/Trampoline_(computing) + +One use case for invoking ``pw_function`` from a C-style API is to automate +the generation of `trampoline layers`_. + .. doxygenfile:: pw_function/pointer.h :sections: detaileddescription @@ -247,7 +259,7 @@ Invoking ``pw::Function`` from a C-style API ScopeGuard ---------- .. doxygenclass:: pw::ScopeGuard - :members: + :members: ------------ Size reports @@ -271,10 +283,25 @@ be used as a reference when sizing external buffers for ``Function`` objects. Design ------ :cpp:type:`pw::Function` is an alias of -`fit::function <https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fit/include/lib/fit/function.h;drc=f66f54fca0c11a1168d790bcc3d8a5a3d940218d>`_. +`fit::function_impl <https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fit/include/lib/fit/function.h>`_. :cpp:type:`pw::Callback` is an alias of -`fit::callback <https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fit/include/lib/fit/function.h;drc=f66f54fca0c11a1168d790bcc3d8a5a3d940218d>`_. +`fit::callback_impl <https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fit/include/lib/fit/function.h>`_. + +.. _module-pw_function-non-literal: + +Why pw::Function is not a literal +================================= +The default constructor for ``pw::Function`` is ``constexpr`` but +``pw::Function`` is not a literal type. Instances can be declared ``constinit`` +but can't be used in ``constexpr`` contexts. There are a few reasons for this: + +* ``pw::Function`` supports wrapping any callable type, and the wrapped type + might not be a literal type. +* ``pw::Function`` stores inline callables in a bytes array, which is not + ``constexpr``-friendly. +* ``pw::Function`` optionally uses dynamic allocation, which doesn't work in + ``constexpr`` contexts (at least before C++20). ------ Zephyr |