C++ Logo

std-proposals

Advanced search

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

From: Thiago Macieira <thiago_at_[hidden]>
Date: Fri, 05 Jan 2024 13:09:15 -0300
On Friday, 5 January 2024 12:51:52 -03 Frederick Virchanza Gotham via Std-
Proposals wrote:
> What I'm proposing would allow some really freaky funky behaviour as
> follows:
>
> struct Base { virtual int Go(float) { return 5; } };
>
> struct Derived1 : Base { int Go(float) override { return 6; } };
>
> struct Derived2 : Base { int Go(float) override { return 7; } };
>
> Derived1 a;
> Derived2 b;
>
> int (*p)(float) = std::memfunc_to_func( &Base::Go, &a);
>
> std::invoke_func_as_memfunc(p, &b, 65.2f);
>
> The above code will invoke the 'Derived2::Go' member function on an object
> of type 'Derived1'. I'm not saying that this is what the feature is
> designed for -- I'm just showing how it works and what it's capable of.

That's what PMFs already do. Why do we need another syntax for the same thing?

> (1) If only 1 argument is supplied, then it returns the address of the>
> implementation of the member function belonging to the class (so if you
> give it '&Base::Go' as the 1st argument then you get back the address of
> Base's implementation of 'Go').

What if there are overloads for the function? How would the new function
distinguish between them?

Do note the syntax you've proposed would need to resolve the overloads
*before* calling memfunc_to_func().

> (2) If 2 arguments are supplied, and if the member function is virtual,
> it looks at the second argument's vtable to get the function's address from
> the vtable. So if you give it '&Base::Go' as the 1st argument then you
> might actually get back the address of Derived1's implementation of 'Go'.

That's unimplementable. You can devirtualise a virtual PMF or virtual function
(look up the function's entry point in the vtable), but you can't re-
virtualise a concrete function pointer. The there will be no pointer for
&Base::Go in either of Derived1 or Derived2's vtable and there's no link to
Base's vtable there either.

Now, because Base::Go is virtual, the PMF formed with it isn't an entry point,
but an index in the vtable. So it would be possible to create larger-than-PMF
object that holds the PMF *and* the devirtualised entry point for the base
implementation or at the level that memfunc_to_func were called on. But
whatever gets returned *is not* a function pointer. It's probably going to be
4*sizeof(void*) on IA-64 ABIs, whoever knows how many with MSVC's weird PMF
implementations.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering

Received on 2024-01-05 16:09:18