Reputation: 731
I have two functions called
void funcBlock(A a, B b, int C, long& R, long& M, double& D)
void funcNormal(A a, B b, long& R, long& M, double& D)
In main method, I would like to use the values from these two function by looping them such as,
main method:
combineFunc cfs[] = { funcBlock, funcNormal }
for (int idx = 0; idx < 2; idx++) //Cause it has two functions to loop over
{
combineFunc cf = cfs[idx];
//Do the rest of the stuffs
}
I encounter error :
error: cannot convert ‘void (*)(A, B, int, long int&, long int&, double&)’ to ‘combineFunc’ in initialization
How do i fix this?
Upvotes: 2
Views: 1041
Reputation: 238321
C++ is a statically typed language. Arrays are homogeneous: All elements of an array have exactly the same type.
A pointer to a function of one type is a different type from a pointer to another function type. Type of a function is determined by its argument and return types. As such, it is not possible to store pointers to functions of different argument lists in the same array.
There are however techniques for "type erasure", which allows simulation of dynamic typing. C++ standard library comes with two heterogeneous wrappers: std::variant
and std::any
. Variant is an implementation of a tagged union. It can be used to store an object from a pre-defined list of types. any
is a type safe wrapper for void*
. it can store an object of any type. So, an array of variant or any
might be what you're looking for.
They are only low level tools though, and for more featured heterogeneous processing, there are existing libraries such as Boost.Hana.
Upvotes: 3
Reputation: 41760
Assuming you have a set of variable to call them with, and all of them have fixed types, you can wrap your functions inside lambdas to normalize their types:
using combineFunc = void(*)(A, B, int, long int&, long int&, double&);
combineFunc cfs[] = {
[](A a, B b, int C, long& R, long& M, double& D){ funcBlock(a, b, C, R, M, D); },
[](A a, B b, int, long& R, long& M, double& D){ funcNormal(a, b, R, M, D); }
};
// do whatever
Upvotes: 1
Reputation: 2250
This is impossible because your functions have different signatures (these are different types). C ++ does not support arrays of elements of different types. But you can match signatures by adding unused parameter, it does not change anything at all, but allows you to put them in one container:
typedef void(*combineFunc)(A, B, int, long int&, long int&, double&);
void funcBlock(A a, B b, int C, long& R, long& M, double& D);
void funcNormal(A a, B b, int unused, long& R, long& M, double& D);
combineFunc cfs[] = { funcBlock, funcNormal };
Another way is to use an array of structures that can store all your functions, like so
struct combineFunc
{
enum TYPE
{
NORMAL,
BLOCK
} type;
combineFunc(void(*nf)(A, B, int, long int&, long int&, double&)) :
type(NORMAL), nf_(nf)
{
}
combineFunc(void(*fb)(A, B, long int&, long int&, double&)) :
type(BLOCK), fb_(fb)
{
}
union
{
void(*nf_)(A, B, int, long int&, long int&, double&);
void(*fb_)(A, B, long int&, long int&, double&);
};
};
CombineFunc cfs[] = { funcBlock, funcNormal };
Upvotes: 4
Reputation: 14454
Your question is best answered with a question.
Within the loop, when you call cf(arguments)
, what arguments would you write between the parentheses? Would the arguments include C
or not?
I think that, if you answer this question, you will see why what you want probably cannot be done until your program has been redesigned a bit. The redesign might be as simple, though, as letting funcNormal()
accept (and ignore) a dummy argument in place of C
.
If the last suggestion is what you want, then
void funcNormal(A a, B b, int, long& R, long& M, double& D)
Notice that the int
, because ignored, is unnamed.
Upvotes: 4