简体   繁体   中英

C++: Generic “call-functions-f-followed-by-g” method?

Is it possible to have a generic method which takes in two functions f and g (both returning void and taking in arguments of the same type) and return a new function which takes in arguments of the same type as f and g and first applies f to the passed arguments and then g ?

Specifically, I want to define something like this:

template <typename FunctionType>
// FunctionType is void(ArgType1 arg1, ArgType2 arg2, ..)
FunctionType CombineTwoFunctions(FunctionType f, FunctionType g) {
  // Using the lambda syntax just for illustration:
  return [f, g](ArgsOf(FunctionType) args) {
     f(args);
     g(args);
  };
}

Not the most optimised code, but it works.

With help of make_function from this answer

template <typename ...Args>
std::function<void(Args...)> CombineTwoFunctionsHelper(std::function<void(Args...)> f, std::function<void(Args...)> g) {

  return [f, g](Args ...args) {
     f(args...);
     g(args...);
  };
}

template <typename F1, typename F2>
auto CombineTwoFunctions(F1 f1, F2 f2) -> decltype(make_function(f1)) {
  return CombineTwoFunctionsHelper(make_function(f1), make_function(f2));
}

void print1(int i, std::string s) {
    std::cout << "print1 " << i << s << std::endl;   
}

void print2(int i, std::string s) {
    std::cout << "print2 " << i << s << std::endl;   
}

int main() {
    auto fg = CombineTwoFunctions(print1, print2);
    fg(1, "test");
}

Full code at Coliru

You should be able to improve it by adding (universal) references to argument and forward them to avoid copies. But note that you cannot move an argument twice.


As @0x499602D2 said in the comment, C++14 make it much eaiser

template <typename F1, typename F2>
auto CombineTwoFunctions(F1 f, F2 g) {
  return [f, g](auto&& ...args) {
     f(args...);
     g(args...);
  };
}

void print1(int i, std::string s) {
    std::cout << "print1 " << i << s << std::endl;   
}

void print2(int i, std::string s) {
    std::cout << "print2 " << i << s << std::endl;   
}

int main() {
    auto fg = CombineTwoFunctions(print1, print2);
    fg(1, "test");
}

Full code at Coliru

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM