C++:通用"call-functions-f-followed-by-g"方法?

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

本文关键字:方法 call-functions-f-followed-by-g C++ 通用      更新时间:2023-10-16

是否可以有一个泛型方法,它接受两个函数fg(都返回void并接受相同类型的参数),并返回一个新函数,该函数接受与fg相同类型的参数,并首先将f应用于传递的参数,然后应用于g

具体来说,我想定义如下:

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);
  };
}

不是最优化的代码,但它可以工作。

在这个答案的make_function的帮助下

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");
}

Coliru 的完整代码

您应该能够通过向参数添加(通用)引用来改进它,并转发它们以避免复制。但请注意,不能移动一个参数两次。


正如@0x499602D2在评论中所说,C++14使其更容易

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");
}

Coliru 的完整代码