SmallFunction
A header-only C++ alternative to std::function that uses fixed-size capture optimization (small-buffer optimization) to avoid heap allocation — 3–5x faster in benchmarks.
SmallFunction is a header-only C++ library providing SmallFun — a drop-in replacement for std::function that avoids heap allocation by storing the callable object in a fixed-size buffer on the stack.
The Problem with std::function
std::function stores its captured closure on the heap, regardless of capture size. This means every construction involves a heap allocation — even for tiny lambdas:
int x = 2;
// Heap allocation happens here:
std::function<int(int)> f = [x](int i) { return i + x; };SmallFun to the Rescue
SmallFun takes the maximum capture size as a template parameter and stores the closure inline on the stack:
#include <SmallFun.hpp>
int x = 2;
// No heap allocation — stored in 64 bytes on the stack:
SmallFun<int(int), 64> f = [x](int i) { return i + x; };If you try to capture more data than the buffer size allows, you get a compile-time error rather than silent heap overflow.
Benchmarks
| Implementation | Time | vs std::function |
|---|---|---|
| Hand-crafted functor | 191 ns | ~6x faster |
SmallFun<..., 32> | 312 ns | ~3.7x faster |
SmallFun<..., 64> | 369 ns | ~3.1x faster |
SmallFun<..., 128> | 346 ns | ~3.3x faster |
std::function | 1141 ns | baseline |
Usage
#include <SmallFun.hpp>
int main() {
int multiplier = 3;
// 32-byte buffer — sufficient for capturing a single int
SmallFun<int(int), 32> triple = [multiplier](int x) {
return x * multiplier;
};
return triple(14); // returns 42
}Implementation
SmallFun combines three C++ patterns:
- Type-erasure — a virtual
Conceptinterface and per-typeModelimplementation - PImpl — managing the lifetime of the type-erased model
- Placement-new — constructing the
Modeldirectly into the stack buffer, bypassing heap allocation
The copy constructor uses a virtual copy(void*) method on the model to deep-copy into a new buffer, handling any managed resources correctly.
Installation
SmallFunction is header-only:
git clone https://github.com/LoopPerfect/smallfunctionAdd the include/ directory to your compiler's include path. Requires C++14.
Related
- Experimenting with Small-Buffer Optimization — The article that explains the implementation in depth with benchmarks.
- value_ptr — The Missing C++ Smart-Pointer — Another C++ library filling a gap in the standard library.