https://github.com/avakar/small_function
Allocation-free move-only alternative to std::function for C++17
https://github.com/avakar/small_function
Last synced: about 2 months ago
JSON representation
Allocation-free move-only alternative to std::function for C++17
- Host: GitHub
- URL: https://github.com/avakar/small_function
- Owner: avakar
- License: 0bsd
- Created: 2021-01-18T15:44:33.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2021-02-06T16:29:13.000Z (over 4 years ago)
- Last Synced: 2025-03-22T15:02:13.972Z (2 months ago)
- Language: C++
- Homepage:
- Size: 11.7 KB
- Stars: 10
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# small_function
Allocation-free move-only alternative to `std::function` for C++17.
## Getting Started
The library is header-only. To use it, clone the repo somewhere
and add the `include` directory to your include path.If you're using CMake, use the FetchContent module.
```cmake
FetchContent_Declare(
avakar.small_function
GIT_REPOSITORY https://github.com/avakar/small_function.git
GIT_TAG main
GIT_SHALLOW 1
)
FetchContent_MakeAvailable(avakar.small_function)target_link_libraries(my_target PUBLIC avakar::small_function)
```## Usage
Include `` and you're good to go.
```cpp
#include
using avakar::small_function;void get_answer(small_function fn)
{
if (fn)
fn(42);
}int main()
{
get_answer([](int x) {
// ...
});
}
```You mustn't invoke `small_function` while it's empty. Default
constructor will construct an empty object. The object
contextually converts to bool indicating whether it's non-empty.By default, `small_function` objects are large enough to contain
a function pointer or a lambda with at most one captured pointer.```cpp
small_function a = [this] {}; // ok, only one capture
small_function b = [this, x] {}; // error, lambda too large
small_function c = &abort; // ok, plain function pointer
```You can adjust the size and alignment of the internal storage.
```cpp
my_overaligned_type o; // assume sizeof(o) == 32, alignof(o) == 16
small_function a = [o]{}; // error, lambda too large
small_function b = [o]{}; // error, after alignment the lambda is too large
small_function c = [o]{}; // ok
small_function d = [o]{}; // ok, even after alignment the lambda will fit
```Zero-sized storage is allowed. Non-capturing lambdas
will fit in those, but function pointers won't.```cpp
small_function a = []{}; // ok, zero-sized lambda
small_function b = [this]{}; // error, lambda too large
small_function c = &abort; // error, function pointer too large
```Template parameters can be deduced automatically from an initializer.
```cpp
small_function a = [] { return 42; };
// decltype(a) == small_functionsmall_function b = [this] { return 42; };
// decltype(b) == small_function
```The function type can include `noexcept`.
```cpp
small_function a = []{}; // error, lambda is not noexcept
small_function b = []() noexcept {}; // ok
small_function c = std::move(b); // ok
small_function d = std::move(c); // error, weakening exception specification
```## Reference
```cpp
template
struct small_function
{
// Creates the `small_function` object with an empty state.
// Such object will be falsy and its `operator()` must not be invoked.
small_function() noexcept;
// Creates the `small_function` object containing `f`.
// This constructor only contributes to the overload set if
//
// * `f` fits in the storage (see below),
// * `f(an...)` is convertible to `R`, and
// * either `noexcept(f(an...))` or `!ne`.
//
// The resulting object will be truthy.
template
small_function(F f) noexcept;// Indicates whether the object is non-empty.
explicit operator bool() const noexcept;// Invokes the contained function object.
// Behavior is undefined if `this` is empty.
R operator()(An &&... an) noexcept(ne)small_function(small_function && o) noexcept;
small_function & operator=(small_function o) noexcept;
};
```An object fits in a storage if the size of the storage is sufficient for
both the object and the maximum padding for alignment. The object might
have to be padded by as many as `alignof(obj) - alignof(storage)` bytes.