Search code examples
c++function-pointers

Function-pointer with variable count and type parameter?


In C++ I need to pass some variables to a function, and I want that function to call back my function pointer with my parameters:

// Example program
#include <iostream>
#include <string>

using namespace std;

typedef void(*callback)(int,int);

void otherFunction(string query, callback c, ??) {
    cout << "otherFunction is processing data" << endl;
    c(??, queryResult);
}

void callbackAfterOtherFunction(int queryId, int result) {
    cout << "Calculation finished: value=" << value << ", value2=" << value2 << ", result=" << result << endl;
}

void doSomething(string query, int queryId) {
  otherFunction(query, callbackAfterOtherFunction, queryId);       
}

int main()
{
  doSomething("QUERY", 1); 
  return 0;
}

This code works, but I find it ugly, because I have to define the parameter list int,int,int for my callback function.

Is there any way in C++ which I can use to simplify this? I.e: otherFunction would get only a functionpointer and some parameters, and it would call that function with provided parameters +its single int calculation result.

Note: callbackAfterOtherFunction is thread-safe, as otherFunction might call it back from a different thread.

Example: Consider a DBManager class which can query data from the DB in asynchron way, so it defines otherFunction which accepts the query (in this case query), and a function pointer which it will call back once data has been queried. But I as DBManager is async I can call otherFunction multiple times before starting to get back the results. Therefore I want to add parameters to otherFunction to mark my queries, so when callbacks give them back, data can be distinguished.

Berto99's solution:

// Example program
#include <iostream>
#include <string>

using namespace std;

template<class Callback, class ...T>
void otherFunction(Callback c, T ...params) {
    cout << "otherFunction is processing data" << endl;
    int res=14;
    //c(params..., (params + ...));
}

void callbackAfterOtherFunction(int value, int value2, int result) {
    cout << "Calculation finished: value=" << value << ", value2=" << value2 << ", result=" << result << endl;
}

void doSomething(int value, int value2) {
    cout << "Processing values: Value=" << value << ", value2=" << value2 << endl;
    otherFunction(callbackAfterOtherFunction, value, value2);
}

int main()
{
    otherFunction(doSomething,2,3);
    return 0;
}

Expected result here would be

Calculation finished: value=2, value2=3, result=14


Solution

  • I would suggest to use variadic template for the parameters, and template argument deduction to avoid declaring the type of the function:

    template<class Callback, class ...T>
    void otherFunction(Callback c, T ...params) {
        cout << "otherFunction is processing data" << endl;
        c(params...); // if you want to have the last parameter to be the sum of all the parameters: c(params..., (params + ...));
    }
    

    The whole code should look like this:

    
    template<class Callback, class ...T>
    void otherFunction(Callback c, T ...params) {
        cout << "otherFunction is processing data" << endl;
        c(params...);
    }
    
    void callbackAfterOtherFunction(int value, int value2, int result) {
        cout << "Calculation finished: value=" << value << ", value2=" << value2 << ", result=" << result << endl;
    }
    
    void doSomething(int value, int value2) {
        cout << "Processing values: Value=" << value << ", value2=" << value2 << endl;
        //otherFunction(value, value2, callbackAfterOtherFunction);
    }
    
    int main()
    {
        otherFunction(doSomething,2,3);
        return 0;
    }
    

    Output:

    otherFunction is processing data
    Processing values: Value=2, value2=3
    

    EDIT:
    If you need the sum of the params, thanks to cdhowie, you can use the previous code and call the callback like this:

    c(params..., (params + ...));
    

    CODE

    
    template<class Callback, class ...T>
    void otherFunction(Callback c, T ...params) {
        cout << "otherFunction is processing data" << endl;
        int res=14;
        c(params..., (params + ...));
    }
    
    void callbackAfterOtherFunction(int value, int value2, int result) {
        cout << "Calculation finished: value=" << value << ", value2=" << value2 << ", result=" << result << endl;
    }
    
    template<class ...T>
    void doSomething(T ... els) {
        cout << "Processing values";
        otherFunction(callbackAfterOtherFunction, els...);
    }
    
    int main()
    {
        doSomething(2,3);
        return 0;
    }