How to store various types of function pointers together?
Normal pointers can be stored using a generic void*
. e.g.
void* arr[10];
arr[0] = pChar;
arr[1] = pINt;
arr[2] = pA;
Sometime back, I came across a discussion that, void*
may not be capable enough to store a function pointer without data-loss in all platforms (say 64-bit and more). I am not sure about this fact though.
If that's true, then what is the most portable way to store a collection of function pointers ? [Note: This 开发者_Go百科question doesn't satisfactorily answer this.]
Edit: I will be storing this function pointers with an index. There is a typecasting associated with every index whenever this collection is accessed. As of now, I am interested only to make an array or vector
of it.]
You can convert a function pointer to another function pointer of any function type and back without loss.
So as long as when you make the call through the function pointer you typecast it back to the correct type first, you can store all of your function pointers in something like:
typedef void (*fcn_ptr)(void); // 'generic' function pointer
fcn_ptr arr[10];
A pointer to a function can be converted to a pointer to a function of a different type with a reinterpret_cast
. If you convert it back to the original type you are guaranteed to get the original value back so you can then use it to call the function. (ISO/IEC 14882:2003 5.2.10 [expr.reinterpret.cast] / 6)
You now only need to select an arbitrary function pointer type for your array. void(*)()
is a common choice.
E.g.
int main()
{
int a( int, double );
void b( const char * );
void (*array[])() = { reinterpret_cast<void(*)()>(a)
, reinterpret_cast<void(*)()>(b) };
int test = reinterpret_cast< int(*)( int, double) >( array[0] )( 5, 0.5 );
reinterpret_cast< void(*)( const char* ) >( array[1] )( "Hello, world!" );
}
Naturally, you've lost a lot of type safety and you will have undefined behavior if you call a function through a pointer to a function of a different type.
Use a union of your function pointer types, this works in both C and C++ and assures sufficient storage for the pointers (which are likely the same size, still...)
There are a few things that make up a function pointer's type.
- the memory address of the code
- the argument signature
- the linkage/name mangling
- the calling convention
- for member functions, some other stuff too
If these features aren't uniform across your function pointers then you can't sensibly store them in the same container.
You can, however bind different aspects into a std::function
which is a callable object that only requires the argument signature and return type to be uniform.
It may be a good time to re-think the problem in terms of virtual functions. Does this mishmash of function pointers have a coherent interface that you can express? If not, then you're doomed anyway :-)
RE: Hasturkun, you can store heterogeneous function pointers in unions, yes, they're just POD, but you will also need to store information about what type of pointer it is so that you can choose the correct member to call. Two problems with this:
- there is a per-item overhead,
- you have to manually check that you're using the right one consistently all the time, this is a burden with nonlocal effects -- it's a spreading poison.
Far better to have one container per type, it will clarify the code and make it safer. Or, use a proxy such as std::function
to make them all have the same type.
精彩评论