At Meeting C++ 2019, Jon Kalb gave a talk about template techniques and mentioned policy classes. See here for the source: https://youtu.be/MLV4IVc4SwI?t=1815
The interesting code snippet in question is:
template<class T, class CheckingPolicy>
struct MyContainer : private CheckingPolicy
{
...
}
I've seen this type of design quite often and I was wondering if inheritance here has any real advantages over composition. In my personal experience I've heard much about the Prefer composition over inheritance paradigm. So the way I would have written the code would be more like this:
template<class T, class CheckingPolicy>
struct MyContainer
{
CheckingPolicy policy;
...
}
There wouldn't be any virtual functions involved. Nevertheless I'd appreciate it if you could share some insights how these differ. I would be especially interested in differences in memory layout and its implications. Would it make a difference if CheckingPolicy
has no data members, but only a check
method or an overloaded call operator?
One possible reason: when you inherit from
CheckingPolicy
, you can benefit from empty base class optimization.If
CheckingPolicy
is empty (i.e. it has no non-static data members other than bit-fields of size0
, no virtual functions, no virtual base classes, and no non-empty base classes), it will not contribute to the size ofMyContainer
.In contrast, when it is a data member of
MyContainer
, even ifCheckingPolicy
is empty, size ofMyContainer
will be increased by at least one byte. At least, because due to alignment requirements you could have additional padding bytes.This is the reason why, e.g., in the implementation of
std::vector
you can find ihnehritance from an allocator. For example, libstdc++'s implementation:Stateless allocators (like
CheckingPolicy
with no non-static data members) will not contribute intostd::vector
's size.In C++20 we'll have
[[no_unique_address]]
to potentially address this issue: whereas empty base optimization is required for standard layout types,[[no_unique_address]]
is just a permission, not a requirement. (Thanks Nicol Bolas for pointing that out.)