B
Ben
Hi, there.
Recently I was working on a problem where we want to save generic
closures in a data structure (a vector). The closure should work for
any data type and any method with pre-defined signature.
When developing this lib, I figured that the
pointer-to-member-function, although seemingly an attractive solution,
does not work well for us.
The size and the memory model of a generic PTMF is not guaranteed,
therefore, cannot be saved in a heterogeneous container.
My solution turned out to be a C callback function pointer.
That is, instead of using a "int T:*f)()", use a "int (*f)(T*)".
Although a wrapper function that does the forward call is needed, it
solved our problem.
For instance:
instead of calling
add_closure(&obj, &MyClass::f);
I do
int mywrapper(*MyClass pobj){
return pobj->f();
}
add_closure(&obj, &mywrapper);
Here, 2 assumptions were made:
1. all pointers have the same size as void*
2. all function pointers have the same size.
Then, the annoying wrapper function makes me think:
Why PTMF in the first place?
What if the language generates the wrapper function implicitly and
makes MyClass::f a regular function pointer of type int (*)
(MyClass*)?
At least it can make my life much easier. And I wonder whose life will
it make harder?
Dislike the ptmf(pobj) syntax? Still like the pobj->ptmf()syntax? No
problem, the language can still do that, as long as it guarantees the
binary memory model of a PTMF is a function pointer. I don't mind
doing a reinterpret_cast here.
Well, just when I'm about to finish, my gut's feeling starts yelling
hard: "No! It can't be right. This must have been thought over 1000
times! You must be missing something here."
"All right, sir. so what am I missing here?"
Recently I was working on a problem where we want to save generic
closures in a data structure (a vector). The closure should work for
any data type and any method with pre-defined signature.
When developing this lib, I figured that the
pointer-to-member-function, although seemingly an attractive solution,
does not work well for us.
The size and the memory model of a generic PTMF is not guaranteed,
therefore, cannot be saved in a heterogeneous container.
My solution turned out to be a C callback function pointer.
That is, instead of using a "int T:*f)()", use a "int (*f)(T*)".
Although a wrapper function that does the forward call is needed, it
solved our problem.
For instance:
instead of calling
add_closure(&obj, &MyClass::f);
I do
int mywrapper(*MyClass pobj){
return pobj->f();
}
add_closure(&obj, &mywrapper);
Here, 2 assumptions were made:
1. all pointers have the same size as void*
2. all function pointers have the same size.
Then, the annoying wrapper function makes me think:
Why PTMF in the first place?
What if the language generates the wrapper function implicitly and
makes MyClass::f a regular function pointer of type int (*)
(MyClass*)?
At least it can make my life much easier. And I wonder whose life will
it make harder?
Dislike the ptmf(pobj) syntax? Still like the pobj->ptmf()syntax? No
problem, the language can still do that, as long as it guarantees the
binary memory model of a PTMF is a function pointer. I don't mind
doing a reinterpret_cast here.
Well, just when I'm about to finish, my gut's feeling starts yelling
hard: "No! It can't be right. This must have been thought over 1000
times! You must be missing something here."
"All right, sir. so what am I missing here?"