This repository is a C++17 implementation of various type erased callable types. It includes:
unique_function
: A Non-copyable drop-in replacement tostd::function
inplace_function
(upcoming): Astd::function
replacement with fixed capacity storage, and guarantee not to allocatefunction_ref
(upcoming): A none owning functionunique_pseudofunction
(upcoming) behave likeunique_function
, but store an overload set instead of an individual function
unique_function
is a proposed standard library type-erased function type that improves std::function
. The interface of unique_function
is almost identical to std::function
, with the following exceptions:
unique_function
does not provides copy operations. This sounds like a restriction, but it means unique_function
can support move-only function objects.
The operator()
of std::function
is const
qualified even when the passed in a mutable function object. For example,
const std::function<int()> f {[x=0]() mutable { return ++x; }};
f(); // fine, returns 1
f(); // returns 2
unique_function
does not suffer this const correctness problem std::function
. In unique_function<F>
, the operator()
is const
qualified only if the function type F
is const qualified. For example,
beyond::unique_function<int()> f1 {[x=0]() mutable { return ++x; }};
beyond::unique_function<int() const> f2 {[x=0]() mutable { return ++x; }}; // Do not compile
beyond::unique_function<int() const> f3 {[x=0]() { return x; }};
const beyond::unique_function<int()> f4 {[x=0]() mutable { return ++x; }};
const beyond::unique_function<int() const> f5 {[x=0]() { return x; }};
f1(); // OK
f3(); // OK
f4(); // Do not compile
f5(); // OK
Not many people are using RTTI for std::function
anyway.
- Total size: 48 bits
- Behavior pointer: 8 bits (Function pointer to polymorphic behaviors except for invocation)
- Function pointer: 8 bits (Function pointer to invocation)
- Storage: 32 bits
"beyond functions" is a header-only library, but the following CMake build options are used to enable test or benchmark during development
BEYOND_FUNCTIONS_BUILD_TESTS
Build unit tests and benchmarksBEYOND_FUNCTIONS_BUILD_TESTS_COVERAGE
Build test with coverage, must enableBEYOND_FUNCTIONS_BUILD_TESTS
first
You can either define macros before every includes or use the CMake build system setting with the same name.
BEYOND_FUNCTIONS_NAMESPACE
: defines the namespace of the library, it isbeyond
by defaultBEYOND_FUNCTIONS_NO_EXCEPTION
: if defined, then the implementation ofoperator()
will not throw and invoking aunique_function
with no underlying target will result in undefined behavior. Note this will not prevent the underlying function from throwing.
Below is a benchmark on invocation overhead of beyond::unique_function
. It is not rigorous, but it indicates that the overhead of beyond::unique_function
is similar to std::function
.
Windows 10, Intel Core i7-8650U CPU @ 1.90GHz (8 CPUs), ~2.1GHz, MSVC 2019
Arch Linux, Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
Tested on:
- Windows
- MSVC 2019
- Linux
- g++-9
- g++-8
- clang-9
- clang-8
- clang-7
- clang-6.0