3

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?

alfC
  • 14,261
  • 4
  • 67
  • 118
  • 1
    See: https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/ – Justin Jan 18 '19 at 00:49
  • You should introduce some virtual functions. Then it might become relevant for more compilers. – Deduplicator Jan 18 '19 at 00:49
  • @Justin, ok, then it seems that for not having wildly large classes this is still needed for VisualStudio (and that they came up with their own workaround.) – alfC Jan 18 '19 at 01:02
  • 2
    EBO is optional, so in both cases, assert might fire. – Jarod42 Jan 18 '19 at 01:08
  • @Jarod42, EBO is optional for the compilers to implement? I guess this craziness will end when C++ rediscovers 0. (when `sizeof(S) == 0`) http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0146r1.html – alfC Jan 18 '19 at 01:13
  • Even with EBO, the size of an empty struct might not be 1 – Caleth Jan 18 '19 at 11:25

1 Answers1

2

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.

P.W
  • 26,289
  • 6
  • 39
  • 76
  • Thanks, I wonder how the attribute is used in the context of inhertance, the examples are for member variables: https://en.cppreference.com/w/cpp/language/attributes/no_unique_address – alfC Jan 18 '19 at 06:28
  • Not sure I get you. The subobjects of inherited classes will have size 0 anyway in the derived class due to EBO. Can you give an example of what you are want to achieve? – P.W Jan 18 '19 at 06:38
  • No, sorry for the confusion, I was just wondering where the attribute would fit in my example. – alfC Jan 18 '19 at 06:42