beyond functions
This repository is a C++17 implementation of various type erased callable types. It includes:
unique_function: A Non-copyable drop-in replacement tostd::functioninplace_function(upcoming): Astd::functionreplacement 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
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:
Move only
unique_function does not provides copy operations. This sounds like a restriction, but it means unique_function can support move-only function objects.
Const-correctness
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
Removal of target and target_type
Not many people are using RTTI for std::function anyway.
Memory Footprint under a 64 bits machine
- 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
Customization
Build Option
“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_TESTSBuild unit tests and benchmarksBEYOND_FUNCTIONS_BUILD_TESTS_COVERAGEBuild test with coverage, must enableBEYOND_FUNCTIONS_BUILD_TESTSfirst
Macros
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 isbeyondby defaultBEYOND_FUNCTIONS_NO_EXCEPTION: if defined, then the implementation ofoperator()will not throw and invoking aunique_functionwith no underlying target will result in undefined behavior. Note this will not prevent the underlying function from throwing.
benchmark
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
Compiler support
Tested on:
- Windows
- MSVC 2019
- Linux
- g++-9
- g++-8
- clang-9
- clang-8
- clang-7
- clang-6.0