fork download
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <iterator>
  5. #include <functional>
  6. #include <memory>
  7. #include <vector>
  8. #include <map>
  9. #include <typeinfo>
  10. #include <stdexcept>
  11. using namespace std;
  12.  
  13. struct Base {
  14. virtual ~Base() = 0;
  15. virtual void print_to(std::ostream &) const = 0;
  16. };
  17. inline Base::~Base() {}
  18.  
  19. template<typename Target>
  20. struct Storage : public Base {
  21. Target value;
  22. Storage (Target t) // screw perfect forwarding :D
  23. : value(std::forward<Target>(t)) {}
  24.  
  25. void print_to(std::ostream & stream) const {
  26. stream << value;
  27. }
  28. };
  29.  
  30. struct Any {
  31. std::shared_ptr<Base const> value;
  32.  
  33. template<typename Target>
  34. Target const & as(void) const {
  35. return
  36. dynamic_cast<Storage<Target> const &>(*value).value;
  37. }
  38. template<typename T>
  39. operator T const &(void) const {
  40. return as<T>();
  41. }
  42. friend std::ostream & operator<<(std::ostream& stream, Any const & thing) {
  43. thing.value->print_to(stream);
  44. return stream;
  45. }
  46. };
  47.  
  48. template<typename Target>
  49. Any make_any(Target && value) {
  50. return Any{std::make_shared<Storage<typename std::remove_reference<Target>::type> const>(std::forward<Target>(value))};
  51. }
  52.  
  53. Any parse_literal(std::string const & literal) {
  54. try {
  55. std::size_t next;
  56. auto integer = std::stoi(literal, & next);
  57. if (next == literal.size()) {
  58. return make_any (integer);
  59. }
  60. auto floating = std::stod(literal, & next);
  61. if (next == literal. size()) {
  62. return make_any (floating);
  63. }
  64. } catch (std::invalid_argument const &) {}
  65. // not very sensible, string literals should better be
  66. // enclosed in some form of quotes, but that's the
  67. // job of the parser
  68. return make_any<std:: string> (std::string{literal});
  69. }
  70.  
  71. std::istream & operator>>(std::istream & stream, Any & thing) {
  72. std::string raw;
  73. if (stream >> raw) {
  74. thing = parse_literal (raw);
  75. }
  76. return stream;
  77. }
  78.  
  79. // Arguments type to the function "interface"
  80. using Arguments = std::vector<Any> const &;
  81. // the interface
  82. using Function = std::function<Any (Arguments)>;
  83.  
  84. // Base case of packing a function.
  85. // If it's taking a vector and no more
  86. // arguments, then there's nothing left to
  87. // pack.
  88. template<
  89. std::size_t N,
  90. typename Fn>
  91. Function pack(Fn && fn) {
  92. return
  93. [fn = std::forward<decltype(fn)>(fn)]
  94. (Arguments arguments)
  95. {
  96. if (N != arguments.size()) {
  97. throw
  98. std::string{"wrong number of arguments, expected "} +
  99. std::to_string(N) +
  100. std::string{" but got "} +
  101. std::to_string(arguments.size());
  102. }
  103. return fn(arguments);
  104. };
  105. }
  106.  
  107. // pack a function to a function that takes
  108. // it's arguments from a vector, one argument after
  109. // the other.
  110. template<
  111. std::size_t N,
  112. typename Arg,
  113. typename... Args,
  114. typename Fn>
  115. Function pack(Fn && fn) {
  116. return pack<N+1, Args...>(
  117. [fn = std::forward<decltype(fn)>(fn)]
  118. (Arguments arguments, Args const &... args)
  119. {
  120. try {
  121. return fn(
  122. arguments,
  123. arguments.at(N),
  124. args...);
  125. } catch (std:: bad_cast const &) {
  126. throw std::string{"argument "} + std::to_string (N) +
  127. std::string{" has wrong type "};
  128. }
  129. });
  130. }
  131.  
  132.  
  133. // transform a function into one that takes its
  134. // arguments from a vector
  135. template<
  136. typename... Args,
  137. typename Fn>
  138. Function pack_function(Fn && fn) {
  139. return pack<0, Args...>(
  140. [fn = std::forward<decltype(fn)>(fn)]
  141. (Arguments arguments, Args const &... args)
  142. {
  143. return make_any(fn(args...));
  144. });
  145. }
  146.  
  147.  
  148. Any apply (multimap<string, Function> const & map, string const & name, Arguments arguments) {
  149. auto range = map.equal_range(name);
  150. for (auto function = range.first;
  151. function != range.second;
  152. ++function) {
  153. try {
  154. return (function->second)(arguments);
  155. } catch (string const &) {}
  156. }
  157. throw string {" no such function "};
  158. }
  159.  
  160.  
  161. int eg(int a,int b){ return a+b;}
  162. int eg(int a,int b, string c){return a+b+c.length();}
  163. double eh(string a){return a.size()/double(2);}
  164. int main(){
  165. multimap<string, Function> func_map;
  166. func_map.insert(make_pair(
  167. "eg",pack_function<int,int>(
  168. static_cast<int(*)(int, int)>(&eg))));
  169. func_map.insert(make_pair(
  170. "eg",pack_function<int,int,string>(
  171. static_cast<int (*)(int, int, string)>(&eg))));
  172. func_map.insert(make_pair(
  173. "eh",pack_function<string>(eh)));
  174.  
  175. // auto p1=make_tuple(1,2);
  176. // if you want tuples, just write a
  177. // function to covert them to a vector
  178. // of Any.
  179. Arguments p1 =
  180. {make_any (1), make_any (2)};
  181. int result1 =
  182. apply(func_map, "eg", p1).as<int>();
  183.  
  184. vector<Any> p2{p1};
  185. p2.push_back(make_any<string> ("test"));
  186. int result2 =
  187. apply(func_map, "eg", p2).as<int>();
  188.  
  189.  
  190. Arguments p3 = {make_any<string>("testagain")};
  191. double result3 =
  192. apply(func_map, "eh", p3).as<double>();
  193.  
  194.  
  195. cout << result1 << endl;
  196. cout << result2 << endl;
  197. cout << result3 << endl;
  198. return 0;
  199. }
  200.  
  201.  
Success #stdin #stdout 0s 3480KB
stdin
Standard input is empty
stdout
3
7
4.5