C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Allow conversion of memfunc pointers to func pointers

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 19 Jan 2024 12:46:39 +0000
On Thursday, January 18, 2024, Thiago Macieira wrote:

>
> Still can't be implemented: there's no link from the type_info object back
> to
> the vtable. The link is one-way and it's from the vtable to the TI.



Just throwing ideas up in the air here, but the compiler could keep a
sorted global array mapping type_info hash codes to vtables:

    array< pair<size_t, void const*>, 2u > const g_vtables = {
         { typeid(MyClass).hash_code(), &_ZTI7MyClass },
         { typeid(YourClass).hash_code(), &_ZTI9YourClass },
    };

The standard library function 'std::get_polymorphic_facilitator' would
perform a binary search through this array. So if a massive program like
Chromium has 6,000 classes, then a worst case binary search would be about
13 checks. On a desktop PC that's less than a microsecond.

Furthermore the standard function 'std::get_polymorphic_facilitator' could
come in four forms:

Form A: You give it a type

    constexpr void const *p = get_polymorphic_facilitator<Base>();

Form B: You give it the address of an object

    Derived obj;
    void const *p = get_polymorphic_facilitator(&obj);

Form C: You give it a type_info

    type_info const &ti = typeid( . . . );
    void const *p = get_polymorphic_facilitator(ti);

Form D: You give it a type_info's hash code

    type_info const &ti = typeid( . . . );
    size_t const hc = ti.hash_code();
    void const *p = get_polymorphic_facilitator(hc);


This request smells like the X-Y problem: in order to do X (the
> devirtualiser), you think you need Y so you're trying to standardise Y. We
> should be talking about X instead. And especially because this X function
> that
> uses Y would need to exist inside the standard library anyway because it's
> not
> portable.
>


I don't think that there's anything wrong with the generic idea of
standardising Y so that X can be implemented in standard-compliant code,
especially if it means that A, B and C can also be implemented alongside X,
taking advantage of Y. Therefore I would strive to make Y as flexible and
as versatile as possible.

So far, the only use I've suggested for 'get_polymorphic_facilitator' is to
turn virtual pointers into direct pointers. I haven't come up with a second
use for it yet but I have a feeling somebody will. Having a pre-compiled
list of use cases isn't the be-all and end-all of engineering; back when
folks were designing the C programming language, switch statements and
loops were designed with very loose restrictions a long time before Thomas
Duff ever came up with his 'Duff's Device'. I'm in favour of keeping things
loose in order to accommodate unforeseen use cases.

If we tell compiler vendors that 'get_polymorphic_facilitator' should
return a pointer to whatever is used to make sure that the correct virtual
function is called -- without explicitly stating 'It gives you the vtable
pointer', then it doesn't restrict how compilers implement virtual
functions. The pointer returned shall be a 'void const *' -- totally
opaque. Or instead maybe have it return:

    struct Polymorphisizer { void const *p; };

I'm tempted to do what Arthur did and fork the GNU linker, try to make a
list of all the vtables and all the type_info's, and then create the
aforementioned sorted map in order to implement 'void const
*std::get_polymorphic_facilitator(type_info const &)'.

Received on 2024-01-19 12:46:41