Embedded std::function alternative: lightweight, deterministic, heap-free.
embed-function is an embedded-friendly lightweight function wrapper implemented based on the C++11 standard, tailored specifically for embedded systems.
While functionally and conceptually analogous to std::function, it offers substantially reduced overhead and superior real-time performance characteristics. Notably, embed-function eliminates dynamic heap memory allocations entirely, ensuring deterministic execution behavior and predictable real-time performance for embedded applications.
A function wrapper is declared as following:
ebd::fn<int (int, float, char) const, 3*sizeof(void*)>
// ^ ^ ^ ^ ^ ^
// | | | | | |
// Return type | | | | |
// Parameters ~|~~~~~|~~~~~| | |
// Qualifier ~~~~~~~~~~~~~~~~~~~~| |
// Buffer size ~~~~~~~~~~~~~~~~~~~~~~~~~~~|- Note: This
Qualifieris used to restrict the callable objects wrapped withinebd::fn, rather thanebd::fnitself.
-
Clone the repository.
-
Add include path
<repo_root>/include. -
In program
#include "embed/embed_function.hpp". -
Use the
ebd::fntemplate class.
#include "embed/embed_function.hpp"
struct Example {
static void static_mem_fn(int) {};
void mem_fn(int) {};
void operator()(int) {};
};
auto main() -> int {
Example e;
ebd::fn<void(int)> fn_;
fn_ = &Example::static_mem_fn;
fn_(123);
fn_ = [e](int arg) { e.mem_fn(arg); };
fn_(456);
fn_ = e;
fn_(789);
}-
Should behave close to a normal function pointer. Small, efficient, no heap allocation.
-
Support the packaging of all callable objects in C++, including:
- Free function.
- Lambda function.
- Functor.
- Static member function.
- Member function.
-
Be usable with C++11 while offering more functionality for later editions.
-
Be constexpr and exception friendly. As much as possible should be declared constexpr and noexcept.
-
Following the above design goals,
ebd::fn,ebd::unique_fn,ebd::safe_fnandebd::fn_viewwere designed for developers to use.
| Wrapper Type | Copyable | View (Non-owning) | Throws on Empty Call | Assert No-Throw (Ctor/Dtor) | Buffer Size | Primary Use Case |
|---|---|---|---|---|---|---|
ebd::fn |
Yes | No | Yes (std::bad_function_call) |
No | Configurable (aligned, default: 2×sizeof(void*)) |
Copyable callable wrapper |
ebd::unique_fn |
No | No | Yes (std::bad_function_call) |
No | Configurable (aligned, default: 2×sizeof(void*)) |
Move-only callable wrapper |
ebd::safe_fn |
Yes | No | No (std::terminate()) |
Yes | Configurable (aligned, default: 2×sizeof(void*)) |
Exception-safe copyable callable wrapper |
ebd::fn_view |
Yes | Yes | No (std::terminate()) |
No | Fixed (2×sizeof(void*), template param unused) |
Lightweight non-owning view of callables |
-
Ownership & Copy:
fn/safe_fnown callables (copyable),unique_fnowns but is move-only,fn_viewis non-owning (view). -
Exception Behavior: Only
fn/unique_fnthrow on empty calls;safe_fn/fn_viewterminate (no exceptions). -
Buffer Configuration:
fn/unique_fn/safe_fnsupport configurable buffer sizes (aligned), whilefn_viewuses a fixed buffer (unused template param).
In order to simplify the use of ebd::fn, function ebd::make_fn() is provided, which can automatically deduce the signature and buffer size of the callable object and create a ebd::fn or ebd::unique_fn object. (Return ebd::unique_ptr only when the callable object is of the move-only type.)
The Concepts language feature is available for use provided that the compiler is configured to support the C++20 standard.
[Optional]means optional.Signature: The signature of the callable object. (such asvoid(int))BufferSize: The buffer size of the callable object. (such as2*sizeof(void*))
// Create empty ebd::fn with specified signature and buffer size.
// If the BufferSize is omitted, it will be set by default (usually 2*sizeof(void*)).
auto f = ebd::make_fn<Signature[, BufferSize]>();
auto f = ebd::make_fn<Signature[, BufferSize]>(nullptr);// Create ebd::fn or ebd::unique_fn from unambiguous callable object.
// If the Signature is omitted, the signature will be deduced from Callable_Object.
auto f = ebd::make_fn[<Signature>](Callable_Object);// Create ebd::fn or ebd::unique_fn from ambiguous callable object with specified signature, such as overload free function, overload member function, etc.
auto f = ebd::make_fn<Signature>(Ambiguous_Callable_Object);