fork(1) download
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. struct yes {};
  5.  
  6. template< typename FUNC >
  7. struct is_callable_with
  8. {
  9. template< typename... PARAMS , typename = decltype(std::declval<FUNC>()(std::declval<PARAMS>()...)) >
  10. yes test(int,PARAMS...) const;
  11.  
  12. void test(...) const;
  13.  
  14. template< typename... PARAMS >
  15. auto operator() (PARAMS...) const -> decltype(test(0, std::declval<PARAMS>()...));
  16. };
  17.  
  18. template< typename FUNC, typename CAPTURE >
  19. using is_callable_by_capture = std::is_same< yes, decltype(std::declval<CAPTURE>()(std::declval<is_callable_with<FUNC>>())) >;
  20.  
  21. // case for when FUNC can be called with the current CAPTURE
  22. template< typename FUNC, typename CAPTURE >
  23. auto curry_impl(FUNC f, CAPTURE c, ...)
  24. {
  25. return c(f);
  26. }
  27.  
  28. // case for when FUNC cannot be called with current CAPTURE
  29. // and we assume this is because an additional entry in the CAPTURE is needed
  30. template< typename FUNC, typename CAPTURE, typename = std::enable_if_t< !is_callable_by_capture<FUNC,CAPTURE>::value > >
  31. auto curry_impl(FUNC f, CAPTURE c, int)
  32. {
  33. return [f,c](auto new_param) {
  34. auto make_new_capture = [new_param](auto... params) {
  35. return [new_param, params...](auto callee) {
  36. return callee(params..., new_param);
  37. };
  38. };
  39.  
  40. return curry_impl(f, c(make_new_capture),0);
  41. };
  42. }
  43.  
  44. template< typename T >
  45. auto curry(T func)
  46. {
  47. return curry_impl(func, [](auto f) {return f();}, 0);
  48. }
  49.  
  50. //--------------------------
  51.  
  52. int print(int a, int b, int c)
  53. {
  54. std::cout << "Printing " << a << " " << b << " " << c << std::endl;
  55. return 99;
  56. }
  57.  
  58. int main() {
  59. auto c_0 = curry(print); // curried function ready to receive arguments
  60. auto c_1 = c_0(1); // first argument provided
  61. auto c_2 = c_1(2); // second argument provided
  62. auto return_value = c_2(3); // final argument
  63.  
  64. std::cout << "Printing returned " << return_value << std::endl;
  65.  
  66. return 0;
  67. }
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
Printing 1 2 3
Printing returned 99