TL;DR We implemented , an alternative to , which implements (a form of small buffer optimization). Whilst is a bit less generic than , it is in some benchmarks. SmallFun std::function fixed-size capture optimization SmallFun std::function 3–5x faster You can . view the code on GitHub Photo by on Pascal Richier Unsplash Background is a convenient way to store lambdas with closures (also known as captures), whilst providing a unified interface. If you are coming from the OOP world, then it might be helpful to understand them as a generalization of the . std::function strategy pattern Before and lambdas, we would create a hand-crafted functor object like this: std::function This repository compares , the hand-crafted and . We find that performs better then by being slighly less generic. std::function Functor SmallFun SmallFun std::function The Missed Opportunity of std::function uses a to provide an unified interface aross all functors for a given signature. std::function PImpl pattern For example, these two instances and have the same size, despite having different captures: f g This is because stores the capture on the . This unifies the size of all instances, but it is also an opportunity for optimization! std::function heap How? Instead of dynamically allocating memory on the , we can place the function object (including its virtual table) into a preallocated location on the . heap stack This is how we implemented , which is used much like : SmallFun std::function Benchmarks The Test To test how quickly we can allocate and call functors, we will be saving all the many instances in a vector and executing them in a loop. The results are saved into another vector to ensure that the optimizer does not optimize away what we are testing. SmallFun Implementation Details To implement , we need to combine three C++ patterns: , and . SmallFun type-erasure PImpl placement-new Type-erasure Type-erasure unifies many implementations into one interface. In our case, every lambda (or functor) has a custom call operator and destructor. We need to automatically generate an implementation for any type the API consumer will be using. This shall be our public interface: And for any callable type with a given signature: Now we can use it the following way: This is quite cumbersome and error prone. The next step will be a container. PImpl PImpl seperates, hides, manages the lifetime of an actual implementation and exposes a limited public API. A straightforward implementation could look like this: This is more or less how is implemented. std::function So how do we remove the heap allocation? Placement-new Placement-new allocates memory at a given address. For example: Putting it All Together Now we only need to do minor changes to remove the heap allocation: As you may noticed, if the ’s size is greater than , bad things will happen! An assert will only catch this at run-time, when it is to late… Luckily, this can be caught at compile-time using . Model<...> SIZE enable_if_t But first, what about the copy constructor? Copy Constructor Unlike the implementation of , we cannot just copy or move a . We also cannot just copy bitwise the memory, since the lambda may manage a resource that can only be released once due to a side-effect. Therefore, we need to make the model able to copy-construct itself for a given memory location. std::function std::shared_ptr We just need to add: Further Remarks As we saw, we can verify at compile-time if a Lambda will fit in our memory. If it does not, we could provide a fallback to heap allocation. A more generic implementation of would take a generic allocator. SmallFun We noticed that we cannot copy the memory just by copying the memory bitwise. However using type-traits, we could check if the underlying data-type is POD and then copy bitwise. Since You’re Here… We created to make it easier to integrate C++ libraries. If you would like try it out, the best place to start is . You can browse the existing packages on or request more over on . Buckaroo the documentation Buckaroo.pm the wishlist _C++ is an unusual language in that it does not yet have a dominant package manager (we’re working on it!). As a result…_hackernoon.com Approaches to C++ Dependency Management, or Why We Built Buckaroo _TL;DR_hackernoon.com Error Handling in C++ or: Why You Should Use Eithers in Favor of Exceptions and Error-codes