fork download
  1. #include <functional>
  2. #include <iostream>
  3. #include <type_traits>
  4. #include <utility>
  5. using namespace std;
  6.  
  7. template <int>
  8. struct int_ {};
  9.  
  10. template <typename...>
  11. struct list {};
  12.  
  13. template <typename L, typename I>
  14. struct index;
  15. template <typename X, typename... XS>
  16. struct index<list<X, XS...>, int_<0>> {
  17. typedef X type;
  18. };
  19. template <typename X, typename... XS, int i>
  20. struct index<list<X, XS...>, int_<i>> {
  21. typedef typename index<list<XS...>, int_<i-1>>::type type;
  22. };
  23.  
  24. template <typename T>
  25. struct remove_m_const {
  26. typedef T type;
  27. };
  28. template <typename X, typename M, typename... XS>
  29. struct remove_m_const<X (M::*)(XS...)> {
  30. typedef X type(XS...);
  31. };
  32. template <typename X, typename M, typename... XS>
  33. struct remove_m_const<X (M::*)(XS...) const> {
  34. typedef X type(XS...);
  35. };
  36.  
  37. template <typename T>
  38. struct normtype {
  39. typedef typename remove_cv<typename remove_pointer<T>::type>::type def;
  40. typedef typename remove_m_const<typename remove_reference<def>::type>::type type;
  41. };
  42.  
  43. template <typename T, int x>
  44. struct argtype_impl;
  45. template <typename T, int x>
  46. struct argtype {
  47. typedef typename normtype<T>::type def;
  48. typedef typename argtype_impl<def, x>::type type;
  49. };
  50. template <typename T, int x>
  51. struct argtype_impl {
  52. typedef typename argtype<decltype(&T::operator()), x>::type type;
  53. };
  54. template <typename T, typename... XS, int x>
  55. struct argtype_impl<T (XS...), x> {
  56. typedef typename index<list<XS...>, int_<x>>::type type;
  57. };
  58.  
  59. template <typename T>
  60. struct rettype_impl;
  61. template <typename T>
  62. struct rettype {
  63. typedef typename normtype<T>::type def;
  64. typedef typename rettype_impl<def>::type type;
  65. };
  66. template <typename T>
  67. struct rettype_impl {
  68. typedef typename rettype<decltype(&T::operator())>::type type;
  69. };
  70. template <typename T, typename... XS>
  71. struct rettype_impl<T (XS...)> {
  72. typedef T type;
  73. };
  74.  
  75. template <typename T, typename U>
  76. auto compose(T a, U b) -> function<decltype(a(b(declval<typename argtype<T, 0>::type>())))(typename argtype<T, 0>::type)> {
  77. return [a, b](typename argtype<T, 0>::type x) { return a(b(x)); };
  78. }
  79.  
  80. template <typename F>
  81. auto curry(F f) -> function<function<typename rettype<F>::type(typename argtype<F, 1>::type)>(typename argtype<F, 0>::type)> {
  82. return [f](typename argtype<F, 0>::type a) { return [f, a](typename argtype<F, 1>::type b) { return f(a, b); }; };
  83. }
  84.  
  85. int main() {
  86. auto sum = [](int x, int y) { return x + y; };
  87. auto mul = [](int x, int y) { return x * y; };
  88. cout << compose(curry(mul)(2), curry(sum)(1))(20) << endl;
  89. }
Success #stdin #stdout 0s 3020KB
stdin
Standard input is empty
stdout
42