Date: Fri, 5 Jan 2024 12:40:21 +0000
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 ).
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
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 ).
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
Received on 2024-01-05 12:40:31