2

I have two functions called

  1. void funcBlock(A a, B b, int C, long& R, long& M, double& D)
  2. 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?

6
  • 2
    What is combineFunc? Commented Mar 14, 2019 at 11:43
  • 5
    They accept different parameter types, and different number of parameters. How do you expect the code know which and how many parameters to pass? Commented Mar 14, 2019 at 11:44
  • 1
    Better tell us what do you want to achieve. Commented Mar 14, 2019 at 11:45
  • cfs[] is an array. All elements of the array need to be of the same type. "Function Pointer" is not a type. Each of the function pointers need to be of the same type. Commented Mar 14, 2019 at 11:51
  • 1
    Possible duplicate of Vector of std::function with different signatures Commented Mar 14, 2019 at 11:51

4 Answers 4

4

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 };
Sign up to request clarification or add additional context in comments.

5 Comments

No, sorry, that isn't what I meant. The word unused is fine as far as the word itself goes. See my answer if you wish. (But I like your answer, too, +1.)
Hi, unfortunately I cant change my function paramaters. So i guess storing them in an array is impossible then.
@user6308605, What C++ standard do you use?
c++11 @DmytroDadyka
@user6308605, in C++ 11 you can create container similar to std::variant based on union type. See updated answer.
4

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.

Comments

3

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.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.