1

i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.

int add(int a, int b)
{
    cout<<a+b;
}
int subtract(int a, int b)
{
    cout<<a-b;
}
int mul(int a, int b)
{
    cout<<a*b;
}

int main()
{

    int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
    unsigned int ch, a = 15, b = 10,c=9;
    ch=2;
    if (ch > 4) return 0;

    (*fun_ptr_arr[ch])(a, b);

    return 0;
}
1
  • Side note, you should check ch > 2, not ch > 4 (or better yet, ch > sizeof(fun_ptr_arr)/sizeof(*fun_ptr_arr)-1). Commented Jan 4, 2017 at 7:17

3 Answers 3

0

The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments

Sign up to request clarification or add additional context in comments.

Comments

0

A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces. Dismantle the data and operation i.e keep them separately.

//Interface which describes any kind of data.
struct IData
{
        virtual ~IData()
        {
        }
};

//Interface which desribes any kind of operation
struct IOperation
{
        //actual operation which will be performed
        virtual IData* Execute(IData *_pData) = 0;

        virtual ~IOperation()
        {
        }
};

Now, every operation knows the kind of data it work on and will expect that kind of data only.

struct Operation_Add : public IOperation
{
            //data for operation addition.
            struct Data : public IData
            {
                    int a;
                    int b;
                    int result;
            };

            IData* Execute(IData *_pData)
            {
                    //expected data is "Operation_Add::Data_Add"
                    Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
                    if(pData == NULL)
                    {
                            return NULL;
                    }

                    pData->result = pData->a + pData->b;
                    return pData;
            }
};

struct Operation_Avg : public IOperation
{
            //data for operation average of numbers.
            struct Data : public IData
            {
                    int a[5];
                    int total_numbers;
                    float result;
            };

            IData* Execute(IData *_pData)
            {
                    //expected data is "Operation_Avg::Data_Avg"
                    Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
                    if(pData == NULL)
                    {
                            return NULL;
                    }

                    pData->result = 0.0f;
                    for(int i = 0; i < pData->total_numbers; ++i)
                    {
                            pData->result += pData->a[i];
                    }
                    pData->result /= pData->total_numbers;
                    return pData;
            }
};

Here, is the operation processor, the CPU.

struct CPU
{
            enum OPERATION
            {
                    ADDITION = 0,
                    AVERAGE
            };

            Operation_Add m_stAdditionOperation;
            Operation_Avg m_stAverageOperation;
            map<CPU::OPERATION, IOperation*> Operation;

            CPU()
            {
                    Operation[CPU::ADDITION] = &m_stAdditionOperation;
                    Operation[CPU::AVERAGE] = &m_stAverageOperation;
            }
};

Sample:

    CPU g_oCPU;

    Operation_Add::Data stAdditionData;
    stAdditionData.a = 10;
    stAdditionData.b = 20;

    Operation_Avg::Data stAverageData;
    stAverageData.total_numbers = 5;
    for(int i = 0; i < stAverageData.total_numbers; ++i)
    {
            stAverageData.a[i] = i*10;
    }

    Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
    if(pResultAdd != NULL)
    {
            printf("add = %d\n", pResultAdd->result);
    }

    Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
    if(pResultAvg != NULL)
    {
            printf("avg = %f\n", pResultAvg->result);
    }

Comments

0

If you have the following functions

int f1(int i);
int f2(int i, int j);

You can define a generic function type like this

typedef int (*generic_fp)(void);

And then initialize your function array

generic_fp func_arr[2] = {
    (generic_fp) f1,
    (generic_fp) f2
};

But you will have to cast the functions back

int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);

Obviously, it does not look like a good way to build a program

To make code look a little bit better you can define macros

#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)

int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);

EDIT

Forgot to mention, you also have to define a type for every type of function

typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params

And to then cast stored pointers to those types

int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);

Here is a complete example

#include <iostream>

typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params

#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)

int f1(int i);
int f2(int i, int j);

int main()
{

    generic_fp func_arr[2] = {
        (generic_fp) f1,
        (generic_fp) f2
    };

    int result_f1_no_macro = ((fi) func_arr[0]) (2);
    int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);


    int result_f1_macro = F1(func_arr[0], 2);
    int result_f2_macro = F2(func_arr[1], 1, 2);

    std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
    std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;

    return 0;
}

int f1(int i)
{
    return i * 2;
}

int f2(int i, int j)
{
    return i + j;
}

The code above produces the following output

4, 3
4, 3

1 Comment

error occurs in this line int result_f1 = ((f1) func_arr[0]) (2); int result_f2 = ((f2) func_arr[1]) (1, 2);

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.