#include <Containers/Function.h>
template<class R, class ... Args>
Function<R(Args...)> class
Function wrapper.
An alternative to std::
To prevent accidental type conversions and potential extra overhead coming from those, the wrapper only accepts functions that match the signature exactly. If a function or a functor has a set of overloads, an overload matching the signature is picked. If you have a function which has a different signature, wrap it in a lambda of a matching singature first.
Function call overhead
On construction, a stateless wrapper lambda is created that then delegates to the particular free function pointer, member function pointer, or a stateful functor / lambda. In the common case this means that invoking a Function always involves two function calls, one for the wrapper lambda and one for the actual function being called.
If the wrapped function is inlineable, in optimized builds this can reduce to just a single function call to the wrapper lambda, which then has the actual function call inlined inside.
Stateful function storage
The Function class is internally made large enough to fit any free or member function pointer. But because member function pointers can increase in size if multiple inheritance and/or virtual inheritance is involved, that space can be repurposed also for saving up to 24 bytes of stateful lambda / functor data on 64-bit platforms (and up to 16 bytes on 32-bit platforms). If larger, the data is allocated on heap instead. For implementation simplicity reasons the state is also allocated if isn't trivially copyable. You can use isAllocated() to check whether the function state needed a heap allocation or not. If heap allocation is undesirable, the Function(NoAllocateInitT, F&&) overload can be used to prevent wrapping any function with state that would need to be allocated.
Type-erased function storage
The class derives from a type-erased FunctionData base, which owns all state and also takes care of proper moving and destruction for non-trivial functors. This allows it to be used as a type-erased storage in various containers for example. Cast the instance back to a concrete Function in order to use it.
Base classes
- class FunctionData
- Function data storage
Public types
- using Type = R(Args...)
- Function type.
Constructors, destructors, conversion operators
-
Function(std::
nullptr_t = nullptr) noexcept - Default constructor.
- Function(R(*)(Args...) f) noexcept
- Wrap a free function pointer.
-
template<class Instance, class Class>Function(Instance& instance, R(Class::*)(Args...) f) noexcept
- Wrap a member function pointer.
-
template<class Instance, class Class>Function(Instance& instance, R(Class::*)(Args...) f&) noexcept
-
template<class Instance, class Class>Function(Instance& instance, R(Class::*)(Args...) const f) noexcept
-
template<class Instance, class Class>Function(Instance& instance, R(Class::*)(Args...) const f&) noexcept
-
template<class Instance>Function(Instance&, std::
nullptr_t) noexcept - Create a null member function pointer.
-
template<class F>Function(F&& f) noexcept(…)
- Wrap a lambda or a functor.
-
template<class F>Function(NoAllocateInitT, F&& f) noexcept
- Wrap a small enough and trivial lambda / functor.
Public functions
- auto operator()(Args... args) -> R
- Call the function pointer.
Function documentation
template<class R, class ... Args>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(std:: nullptr_t = nullptr) noexcept
Default constructor.
Creates a nullptr function.
template<class R, class ... Args>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(R(*)(Args...) f) noexcept
Wrap a free function pointer.
If f is nullptr, the constructor is equivalent to Function(std::
template<class R, class ... Args>
template<class Instance, class Class>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(Instance& instance,
R(Class::*)(Args...) f) noexcept
Wrap a member function pointer.
Default, &, const and const & r-value overloads are supported, && and const && however isn't, as the member function is always called on a l-value. If f is nullptr, the constructor is equivalent to Function(std::
template<class R, class ... Args>
template<class Instance, class Class>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(Instance& instance,
R(Class::*)(Args...) f&) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class R, class ... Args>
template<class Instance, class Class>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(Instance& instance,
R(Class::*)(Args...) const f) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class R, class ... Args>
template<class Instance, class Class>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(Instance& instance,
R(Class::*)(Args...) const f&) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
template<class R, class ... Args>
template<class Instance>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(Instance&,
std:: nullptr_t) noexcept
Create a null member function pointer.
Equivalent to Function(std::
template<class R, class ... Args>
template<class F>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(F&& f) noexcept(…)
Wrap a lambda or a functor.
The functor is expected to exactly match the signature, no implicit conversions on either the arguments or return type are allowed. If the lambda capture or functor state is small enough and trivially copyable, it's stored inline, otherwise allocated on heap.
template<class R, class ... Args>
template<class F>
Death:: Containers:: Function<R(Args...)><R, Args>:: Function(NoAllocateInitT,
F&& f) noexcept
Wrap a small enough and trivial lambda / functor.
Compared to Function(F&&) compiles only if the lambda capture or functor state is small enough and trivially copyable to not need to be allocated on heap.
Note that there's no NoAllocateInit variant for free or member function pointers, as they never need to be allocated on heap.
template<class R, class ... Args>
R Death:: Containers:: Function<R(Args...)><R, Args>:: operator()(Args... args)
Call the function pointer.
Expects that the pointer is not nullptr.