I have been looking through GCC implementation of std::function (got there while debugging and went off on a tangent).
From what I can see it stores small types inside local storage and anything that does not fit it allocates via new operator.
However the constructor also does check the __location_invariant metafunction, which is a wrapper around std::trivially_copyable trait, and if it isn't "location invariant", it also allocates it on the heap.
I do not completely understand why does it do it, as from what I understand
::new (storage) T(args)
should provide the same result as
new T(args)
With the exception that the in-place constructor does not allocate any memory.
It would make more sense to me if it, for example, used a single reference-counted object to store the "location invariant" types that are too large to fit in local storage, as that would decrease amount of allocations and copying. With non-invariant objects being allocated and copied every time, as being "location-dependant" they cannot all refer to the same storage.
The implementation does seem to just heap-allocate anything that does not fit and/or is not location invariant (at least i did not see it doing so?), so I am quite confused why does it need to check for location invariance, if there is no apparent difference in functionality.