C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Standard support for different ABI's for class vtables

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sun, 1 Jun 2025 17:01:11 +0100
On Sun, Jun 1, 2025 at 12:46 AM Frederick Virchanza Gotham wrote:
>
>
> I've been saying for a while now that C++ is held back by Microsoft's implementation of polymorphism; I posted the following here 6 months ago:
>
> https://lists.isocpp.org/std-proposals/2024/11/11541.phpp


The link I gave above is broken, here's the correct one:
https://lists.isocpp.org/std-proposals/2024/11/11541.php

I've been thinking about a way to accommodate the problem of the
Microsoft compiler sometimes not putting the vtable pointer at the
beginning of the object, and the consequences that this has for the
entire worldwide C++ community. The two consequences are:

    (1) Cannot use dynamic_cast on a void* to get the most derived object
    (2) Cannot get the type_info from a void*

If we were to have a new standard library class, say 'std::polymorph',
then it could be used as follows:

    MyClass obj;
    std::polymorph p = obj; // implicit conversion

The class, std::polymorph, would be the same size as a pointer. On
every compiler except Microsoft, the value stored in 'p' will always
be the same as '&obj'. However on the Microsoft compiler, it might be
adjusted by a few bytes, for example if we were to have:

    class Base { int n; };
    class MyClass : public Base { virtual ~MyClass(void) noexcept {} };

then the address stored in 'p' will be equal to '(char*)&obj + 4'
because the vtable pointer appears after 'n' inside the object.

Once we have 'p', we can then do the two things I mentioned in the
above linked post:

    (1) Use dynamic_cast on an std::polymorph to get the most derived object
    (2) Get the type_info from an std::polymorph

But of course, the next question is, if we have 'p', then can we
determine the address of the object? I think this is always possible
because we can get the RTTICompleteObjectLocator object from the
vtable pointer, and the locator object contains a member called
'offset' which is "the offset of the vtable pointer relative to the
start of the complete object".

So in an ideal world, Microsoft would change its ABI. But failing
that, we could have an 'std::polymorph' which is the same size as a
'void*'. Maybe another name such as 'handle_to_polymorph' would be
more suitable.

Received on 2025-06-01 16:01:22