fork(1) download
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <iterator>
  5. #include <functional>
  6. #include <vector>
  7. #include <map>
  8. using namespace std;
  9.  
  10. // Arguments type to the function "interface"
  11. using Arguments = std::vector<int> const &;
  12. // the interface
  13. using Function = std::function<int (Arguments)>;
  14.  
  15. // Base case of packing a function.
  16. // If it's taking a vector and no more
  17. // arguments, then there's nothing left to
  18. // pack.
  19. template<
  20. std::size_t N,
  21. typename Fn>
  22. Function pack(Fn && fn) {
  23. return
  24. [fn = std::forward<decltype(fn)>(fn)]
  25. (Arguments arguments)
  26. {
  27. if (N != arguments.size()) {
  28. throw
  29. std::string{"wrong number of arguments, expected "} +
  30. std::to_string(N) +
  31. std::string{" but got "} +
  32. std::to_string(arguments.size());
  33. }
  34. return fn(arguments);
  35. };
  36. }
  37.  
  38. // pack a function to a function that takes
  39. // it's arguments from a vector, one argument after
  40. // the other.
  41. template<
  42. std::size_t N,
  43. typename Arg,
  44. typename... Args,
  45. typename Fn>
  46. Function pack(Fn && fn) {
  47. return pack<N+1, Args...>(
  48. [fn = std::forward<decltype(fn)>(fn)]
  49. (Arguments arguments, Args const &... args)
  50. {
  51. return fn(
  52. arguments,
  53. arguments[N],
  54. args...);
  55. });
  56. }
  57.  
  58.  
  59. // transform a function into one that takes its
  60. // arguments from a vector
  61. template<
  62. typename... Args,
  63. typename Fn>
  64. Function pack_function(Fn && fn) {
  65. return pack<0, Args...>(
  66. [fn = std::forward<decltype(fn)>(fn)]
  67. (Arguments arguments, Args const &... args)
  68. {
  69. return fn(args...);
  70. });
  71. }
  72.  
  73.  
  74. int add (int lhs, int rhs) {
  75. return lhs + rhs;
  76. }
  77.  
  78.  
  79. int main(int, char**) {
  80. std::map<std::string, Function> operations;
  81. operations ["add"] = pack_function<int, int>(add);
  82. operations ["sub"] = pack_function<int, int>(
  83. [](auto lhs, auto rhs) { return lhs - rhs;});
  84. operations ["sum"] = [] (auto summands) {
  85. int result = 0;
  86. for (auto e : summands) {
  87. result += e;
  88. }
  89. return result;
  90. };
  91. std::string line;
  92. while (std::getline(std::cin, line)) {
  93. std::istringstream command{line};
  94. std::string operation;
  95. command >> operation;
  96. std::vector<int> arguments {
  97. std::istream_iterator<int>{command},
  98. std::istream_iterator<int>{} };
  99. auto function = operations.find(operation);
  100. if (function != operations.end ()) {
  101. std::cout << line << " = ";
  102. try {
  103. std::cout << function->second(arguments);
  104. } catch (std::string const & error) {
  105. std::cout << error;
  106. }
  107. std::cout << std::endl;
  108. }
  109. }
  110. return 0;
  111. }
Success #stdin #stdout 0s 3428KB
stdin
add 5 4
sub 3 2
add 1 2 3
add 4
sum 1 2 3 4
sum
stdout
add 5 4 = 9
sub 3 2 = 1
add 1 2 3 = wrong number of arguments, expected 2 but got 3
add 4 = wrong number of arguments, expected 2 but got 1
sum 1 2 3 4 = 10
sum = 0