fork download
  1. #include <iostream>
  2. #include <functional>
  3.  
  4. //using namespace std;
  5.  
  6. template <typename ...Args>
  7. std::function<void(Args...)> wrapLog(std::function<void(Args...)> f) {
  8.  
  9. return [f](Args... args) { //捕获函数对象f
  10. std::cout << "start" << std::endl;
  11. f(args...);
  12. std::cout << "finish" << std::endl;
  13. };
  14. }
  15.  
  16. template <typename> struct function_traits_base;
  17.  
  18. template <typename Function>
  19. struct function_traits : public function_traits_base<decltype(&Function::operator())> {
  20.  
  21. };
  22.  
  23. //lambda 转换为 std::function<void(Args...)> 需要知道 传入参数类型和返回值类型 ,这里进行萃取
  24. template <typename ClassType, typename ReturnType, typename... Args>
  25. struct function_traits_base<ReturnType(ClassType::*)(Args...) const> //Args...可变模板参数 ,因为不知道lambda将传入几个参数
  26. {
  27. //typedef ReturnType (*pointer)(Args...);
  28. typedef std::function<ReturnType(Args...)> function;
  29. };
  30.  
  31. template <typename Function>
  32. typename function_traits<Function>::function //返回值类型 function_traits<Function>::function
  33. to_function(Function& lambda) //函数名to_function,传入参数lambda
  34. {
  35. return typename function_traits<Function>::function(lambda); //将lambda传入function_traits<Function>::function
  36. }
  37.  
  38. //functional里面有定义了个std::plus。如果把plus定义为global的,访问时在global查找定义就会和std::plus冲突,产生二义。
  39. //auto plus = [](int a, int b) { std::cout << a + b << std::endl; }; //error,Plus不明确
  40. std::function<void(int, int)> plus = [](int a, int b) { std::cout << a + b << std::endl; };
  41.  
  42. int main(int argc, char *argv[]) {
  43. //这是简单的lambda,其中包含琐碎的计算:
  44. //auto plus = [](int a, int b) { cout << a + b << endl; };
  45.  
  46. //lambda和 std :: function 无法完成转换
  47. //auto loggedPlus = wrapLog(plus); //test1
  48.  
  49. //强制转换,OK,该行可以编译,但是很难看
  50. auto loggedPlus = wrapLog(static_cast<std::function<void(int, int)>>(plus)); //test2
  51. loggedPlus(2, 3);
  52.  
  53. //暂时最佳解决方案
  54. auto loggedPluss = wrapLog(to_function(plus)); //通过调用to_function函数 将 lambda表达式plus 转换为std::function<void(Args...)> 形式
  55. loggedPluss(2, 3);
  56.  
  57. return 0;
  58. }
Success #stdin #stdout 0s 4488KB
stdin
Standard input is empty
stdout
start
5
finish
start
5
finish