0

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

Daniel
  • 2,318
  • 2
  • 22
  • 53
  • Template functor? The problem is under-specified. Show some code of how you _want_ it to work, where `callback` is a placeholder type that doesn't exist. Be as specific as you can about the scenarios you want it to be able to handle. – cdhowie Jul 20 '20 at 17:50
  • 1
    Look at this post. https://stackoverflow.com/questions/11037393/c-function-pointer-to-functions-with-variable-number-of-arguments – Kungfu Frog Jul 20 '20 at 18:05
  • Look at this post. This may help you. https://stackoverflow.com/questions/11037393/c-function-pointer-to-functions-with-variable-number-of-arguments – Kungfu Frog Jul 20 '20 at 18:07

3 Answers3

1

The simplest solution is to use a template like this:

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

using namespace std;

template<typename C>
void otherFunction(int value, int value2, C c) {
    cout << "otherFunction is processing data" << endl;
    c(value, value2, value+value2);
}

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()
{
  doSomething(2,3); 
  return 0;
}
Bernd
  • 2,113
  • 8
  • 22
1

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;
}
Alberto Sinigaglia
  • 12,097
  • 2
  • 20
  • 48
  • Based on the sample code, the call should be `c(params..., 0 + ... + params);` assuming addition. OP talks about having an "int result" but doesn't clarify the operation. – cdhowie Jul 20 '20 at 17:57
  • @cdhowie yes well i don't really get what he meant with _its single int calculation result._ and what you are suggesting is actually the best interpretation that i had so far – Alberto Sinigaglia Jul 20 '20 at 17:59
  • Yeah, that's why I left the comment I did on the question. There's not enough information in the question to conclusively say what the OP is looking for. – cdhowie Jul 20 '20 at 18:00
  • @cdhowie actually the code you provided does not compile (don't know if that was the intent), however, added the same logic with code that compiles at the bottom – Alberto Sinigaglia Jul 20 '20 at 18:04
  • It doesn't compile with your code because you made incompatible changes. Try taking OP's code and changing _only_ `otherFunction()`. – cdhowie Jul 20 '20 at 18:05
  • @cdhowie i've only changed the order of the parameters... – Alberto Sinigaglia Jul 20 '20 at 18:07
  • Actually the point would be to keep `otherFunction` from being defined multiple times for multiple scenario (with different parameters). – Daniel Jul 20 '20 at 18:09
  • @Daniel and this does exactly it (ok not at compile time) – Alberto Sinigaglia Jul 20 '20 at 18:10
  • Yes, I know, just wanted to reflect :) Will try soon and accept, thanks! – Daniel Jul 20 '20 at 18:12
  • I can't make it work, updated the question with your code, and expected result, kindly check it. – Daniel Jul 20 '20 at 18:30
  • @Daniel if you want to do that, you have to do the same thing on `doSomething` (i'll post the code at the bottom of the answer) – Alberto Sinigaglia Jul 20 '20 at 18:33
  • Right, I see. OP's code makes the same mistake. It looks like the order in which the functions get invoked in OP's code is wrong for what they are trying to do. – cdhowie Jul 20 '20 at 18:35
  • New code for me prints `Calculation finished: value=2, value2=3, result=5`, I need `Calculation finished: value=2, value2=3, result=14`. I.e 3rd parameter does not depend on first two at all. – Daniel Jul 20 '20 at 18:39
  • Oh, OK I guess I have to put all variables before the variadic to work. – Daniel Jul 20 '20 at 18:43
1

This will allow you to calculate any number of parameters:

int a = 2;
int b = 3;
anotherFunction(acallbackAfterOtherFunction, doSomething,a,b,4,5,6);
using namespace std;

template<class Callback, typename T>
int otherFunction(Callback c, T one) {
    cout << "otherFunction is processing ONE data " << one << endl;
    return one;
}

template<class Callback, typename A, typename... T>
int otherFunction(Callback c, A one, T... params) {
    cout << "otherFunction is processing data" << endl;
    
    return c(otherFunction(c, one), otherFunction(c, params...));
}

template<typename P, class Callback, typename A, typename... T>
int anotherFunction(P p, Callback c, A one, T... params) {
    cout << "anotherFunction is processing data" << endl;
    int i = c(otherFunction(c, one), otherFunction(c, params...));
    p (i);
    return i;
}

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

void acallbackAfterOtherFunction(int result) {
    cout << "Calculation finished: result=" << result << endl;
}

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

int main()
{
    int a = 2;
    int b = 3;
    int r = anotherFunction(acallbackAfterOtherFunction, doSomething,a,b,4,5,6);
    cout << "R: " << r << endl;
    return 0;
}

Manuel
  • 2,526
  • 1
  • 13
  • 17