Home > Software engineering >  How to pass a template function to another function and apply it
How to pass a template function to another function and apply it

Time:05-11

// I can't change this function!
template<typename Function, typename... Args>
void RpcWriteKafka(Function func, Args&&... args) {
    func(std::forward<Args>(args)...);
}

// I can change this one if necessary.
template<typename FUNC, typename... Args, typename CALLBACK, typename... CArgs>
void doJob(std::tuple<CALLBACK, CArgs&&...> tp, FUNC func, Args&&... args) {
    // SetValues(std::forward<Args>(args)...);
    std::apply(func, tp);
}

int main() {
    doJob(std::make_tuple([](int i){}, 1), RpcWriteKafka, 1);

    return 0;
}

As you see, some library provided the template function RpcWriteKafka. It needs the parameter about a callback function(func) and its parameters(args...).

I want to define my own function doJob, which allows me to call it like this: doJob(std::make_tuple([](int i){}, 1), RpcWriteKafka, 1);. I'm expecting that the first parameter, which is a std::tuple, could be passed to the second parameter RpcWriteKafka.

Why do I used std::tuple: How to pass a function with parameter pack to a function with parameter pack

For now, it can't be compiled.

The compiler generated two errors:

  1. mismatched types 'CArgs&&' and 'int', which comes from the 1 in that tuple;
  2. the second parameter RpcWriteKafka is unresolved overloaded function type.

So how to solve the two issues? Is it possible to define such a function doJob so that I can call it easily as shown in the main above?

CodePudding user response:

First, the first parameter type of doJob should be std::tuple<CALLBACK, CArgs...> instead of std::tuple<CALLBACK, CArgs&&...> since CArgs&& cannot be deduced in such context.

Second, since RpcWriteKafka is a function template, you can't pass it to doJob like this, instead, you need to wrap it with lambda, so this should work (I omit the Args&&... because it is not used)

template<typename CALLBACK, typename... CArgs, typename FUNC>
void doJob(std::tuple<CALLBACK, CArgs...>&& tp, FUNC func) {
  std::apply(func, tp);
}

int main() {
  doJob(std::make_tuple([](int i){}, 1), 
    [](auto... args) { RpcWriteKafka(args...); });
}
  • Related