c++c++11multiple-inheritancebase-classempty-class

Chained inheritance of empty classes, still necessary?


Are there still good reasons to use chainned base cases rather than a flat multiple inheritance?

It used to be the case that some classes were designed to be inherted in chain. I think this was to force the empty base class optimization. I understand this is how Boost.Operators were designed.

struct empty{};

template<class Base = empty>
struct A : Base{}; 

template<class Base = empty>
struct B : Base{}; 

template<class Base = empty>
struct C : Base{};

struct S : A<B<C<>>>{};

int main(){static_assert(sizeof(S)==1, "!");}

Is this necessary anymore in new compilers (today is 2019), or I can ditch all that complexity and live with normal inheritance?

struct A{}; 

struct B{}; 

struct C{};

struct S : A, B, C{};

int main(){static_assert( sizeof(S) == 1 , "!");}

does it serve any primary or secondary purpose anymore?


Solution

  • The standard states in [class.derived]/7 that:

    A base class subobject may be of zero size.

    This means that EBO is not mandatory for compilers to implement. However nearly all compilers implement it.

    From C++20 onwards, there is the [[no_unique_address]] attribute which can be applied to the empty member subobjects:

    The empty member subobjects are permitted to be optimized out just like the empty bases if they use the attribute [[no_unique_address]]. Taking the address of such member results in an address that may equal the address of some other member of the same object.