Templates provide a convenient mechanism to support policies. Probably the most widely used example is std::unique_ptr with its Deleter template parameter. Let’s take a look at one of the ways to do something like this
It’s certainly not the only way to achieve this and in this particular case it would be possible to avoid usage of member field and use a local variable directly in destructor. But using a member field can be very useful in case of customizations. For instance, policy can have other member functions that can be used at different stages of lifecycle to customize its behavior.
So, sounds like this approach may be useful and is easy to use. What are the downsides?
Looks like the size of the struct is 2 instead of much more reasonable 1. But why? It’s because even empty classes take at least 1 byte. You can read C++ creator’s explanation for why that’s the case.
Ok, so our onDeleter has to take at least 1 byte, but what if it didn’t have to have a unique address? Let’s try
Newly introduced no_unique_address attribute allows compiler to not bother ensuring address uniqueness for onDeleter, so it can reuse ch’s address.
You can use compiler explorer to convince yourself.
There is a gotcha though - each non-unique address must be mapped to a unique byte in struct. So if we add a second deleter, the size of the struct will increase to 2.
Saving 1 byte may not seem like a big deal, but when dealing with large collections, it can have significant impact on cache hit rate and as such runtime.