C++ Logo

std-proposals

Advanced search

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

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Fri, 5 Jan 2024 19:27:00 +0100
Hi Lénárd,   what about the implementations with different calling convention? (I.e. not using the first parameter as the instance pointer.)   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?   -----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 -- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-01-05 18:27:02