Why is the empty base class optimization (EBO) is not working in MSVC?

Why is the empty base class optimization (EBO) not being fully applied in Visual C++?

If I have a lot of base classes, is there any way for me to help the compiler make this optimization?

#include <iostream>

struct T1 { };
struct T2 { };
struct T3 { };
struct T4 { };
struct T5 { };
struct T6 { };

struct Test : T1, T2, T3, T4, T5, T6 { };

int main() { std::cout << sizeof(Test); }   // Prints 5

This is a longstanding bug in the Visual C++ compiler. When a class derives from multiple empty base classes, only the initial empty base class will be optimized using the empty base optimization (EBO).

This issue was reported on Microsoft Connect in 2006: Empty Base Optimization Not Working Properly. At the moment, old bugs are not visible on Microsoft Connect. I am told that this is a temporary issue, though I do not know when it will be resolved. In the meantime, the following is the response to the bug from Jonathan Caves, who is one of the developers on the Visual C++ compiler team:

Hi: unfortunately even though this is a bug in the Visual C++ object model we are unable to fix it at this time given that fixing it would potentially break a lot of existing programs as the sizes of objects would change. Hopefully in the future we may be able to address this issue but not for the next release of the product.

Thanks for reporting the issue.


The 'official' stance is MSVC will only do EBO for single inheritance, unfortunately the bug report where this is stated was deleted by MS, so all that remains is an older question on MSDN that points it out and references the now deleted bug report.


Since Visual Studio 2017 Update 2, there is a fix for this... but is it disabled by default. And you have to explicitly enable it for every class separately:

    struct __declspec(empty_bases) Test : T1, T2, T3, T4, T5, T6 { };
    //     ^^^^^^^^^^^^^^^^^^^^^^^

    static_assert(1 == sizeof(Test));

Sadly, this still holds true even for /std:c++latest and /permissive- even in Visual Studio 2019: There is no way of setting it globally.