C++ Logo

std-proposals

Advanced search

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

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Fri, 05 Jan 2024 20:32:17 +0100
Hi,

On 5 January 2024 19:27:00 CET, Sebastian Wittmeier via Std-Proposals <std-proposals_at_[hidden]> wrote:
>Hi Lénárd,
>
>
>what about the implementations with different calling convention? (I.e. not using the first parameter as the instance pointer.)

Do you have examples of such implementations?

>Would they create a function stub for those member functions to shift the parameters into the correct register, and memfunc_to_func would return a pointer to that stub instead?

I don't think that this is feasible in general. If GCC supports such an ABI then it could be checked what its bound member function extension does.

Having said that this feature could be optional, but could still be present on most implementations, not unlike uint8_t. It would certainly weaken the motivation for standardisation though.

>
>-----Ursprüngliche Nachricht-----
>Von:Lénárd Szolnoki via Std-Proposals <std-proposals_at_[hidden]>
>Gesendet:Fr 05.01.2024 19:11
>Betreff:Re: [std-proposals] Allow conversion of memfunc pointers to func pointers
>An:std-proposals_at_[hidden];
>CC:Lénárd Szolnoki <cpp_at_[hidden]>;
>Hi,
>
>I think this idea has some merit, and this even has precedent in the form of a GCC extension:
>
>https://gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html
>
>The GCC extension unfortunately uses C-style cast for the syntax, overloading it with yet another meaning, but featurewise I think it's OK.
>
>
>On 5 January 2024 13:40:21 CET, Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>At least 95% of C++ implementations nowadays use a calling convention
>>that performs the invocation of a class's member function by moving
>>all the arguments down one position, and putting the 'this' pointer in
>>the first position.
>>
>>So for example on x86_64 on Microsoft Windows, if a normal function
>>takes three integer arguments, these arguments will be put in RCX,
>>RDX, R8. If a member function takes three integer arguments, then
>>RCX,RDX,R8 will be moved down to RDX,R8,R9 and then the 'this' pointer
>>will be put in RCX.
>>
>>Only about 4 implementations of C++ leave the function arguments alone
>>and store the 'this' pointer in another register (for a list of them,
>>see page 4 of http://www.virjacode.com/papers/paper_nrvo_latest.pdf ).
>
>This seems to discuss the calling convention for passing the address of the return slot, not the this parameter.
>
>>
>>So anyway, what if we were able to do the following in Standard C++?
>>
>> struct Monkey {
>> unsigned i;
>> virtual unsigned Go(double x) { return i +
>>static_cast<unsigned>(x + 0.5); }
>> };
>>
>> int main(void)
>> {
>> Monkey m = { 8u };
>>
>> unsigned (*p)(double) = std::memfunc_to_func( &Monkey::Go, &m );
>>
>> std::invoke_func_as_memfunc(p, &m, 45.3);
>> }
>>
>>The function 'memfunc_to_func' would take two arguments:
>> (1) A pointer to a member function for class T
>> (2) A pointer to an object of type T
>>
>>It needs the second argument just in case the member function is
>>virtual and it needs to look at the vtable of the supplied object.
>>
>>The function 'invoke_fun_as_memfunc' takes two or more arguments:
>> (1) A normal function pointer which holds the address of a member function
>> (2) An address of an object
>> (3) Any arguments to be passed to the member function
>
>This looks mostly OK, but there are some things that look off:
>
>1. I think memfunc_to_func should return unsigned (*)(Monkey*, double) in the example above.
>2. invoke_func_as_memfunc shouldn't exist, you can just call (or std::invoke) the returned ptr without special treatment.
>
>Cheers,
>Lénárd

Received on 2024-01-05 19:32:23