I tend to use type erasure technique quite a bit. It typically looks like this:
class YetAnotherTypeErasure
{
public:
// interface redirected to pImpl
private:
// Adapting function
template ...
friend YetAnotherTypeErasure make_YetAnotherTypeErasure (...);
class Interface {...};
template <typename Adaptee>
class Concrete final : public Interface {
// redirecting Interface to Adaptee
};
std::unique_ptr<Interface> pImpl_; // always on the heap
};
std::function
does something similar, but it has a small buffer optimization, so if Concrete<Adaptee>
is smaller than smth and has nothrow move operations, it will be stored in it. Is there some generic library solution to do it fairly easy? For enforcing small buffer only storing at compile time? Maybe something has been proposed for standardisation?
I know nothing about the small buffer optimization required by the standard or any proposal, though it is often allowed or encouraged.
Note that some (conditionally) non-throwing requirements on such types effectively require the optimization in practice because alternatives (like non-throwing allocation from emergency buffers) seem insane here.
On the other hand, you can just make your own solution from scratch, based on the standard library (e.g. std::aligned_storage
). This may still verbose from the view of users, but not too hard.
Actually I implemented (not proposed then) any
with such optimization and some related utilities several years ago. Lately, libstdc++'s implementation of std::experimental::any
used the technique almost exactly as this (however, __
prefixed internal names are certainly not good for ordinary library users).
My implementation now uses some common helpers to deal with the storage. These helpers do ease to implement the type erasure storage strategy (at least fit for something similar to any
enough). But I am still interested in more general high-level solution to simplify the interface redirecting.
There is also a function
implementation based directly on the any
implementation above. They support move-only types and sane allocator interface, while std
ones not. The function
implementation has better performance than std::function
in libstdc++ in some cases, thanks to the (partially no-op) default initialization of the underlying any
object.
I found a reasonably nice solution for everyday code - use std::function
With tiny library support to help with const correctness, the code get's down to 20 lines: https://gcc.godbolt.org/z/GtewFI
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With