fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <string>
  4. #include <sstream>
  5.  
  6. struct Variant
  7. {
  8. template<typename T>
  9. explicit Variant(T x) { std::stringstream ss; ss << x; impl = ss.str(); }
  10.  
  11. template<typename T>
  12. friend T cast(Variant v) { std::stringstream ss(v.impl); T t; ss >> t; return t; }
  13.  
  14. private:
  15. std::string impl;
  16. };
  17.  
  18. namespace details
  19. {
  20. template<typename... Ts> struct type_seq {};
  21.  
  22. template<unsigned... Ns> struct num_seq {};
  23. template<unsigned I, unsigned... Ns> struct gen_num_seq : gen_num_seq<I - 1, I - 1, Ns...> {};
  24. template<unsigned... Ns> struct gen_num_seq<0, Ns...> { typedef num_seq<Ns...> type; };
  25.  
  26. template<typename F, unsigned... Is, typename... Ts>
  27. Variant invoke2(F f, Variant* args, num_seq<Is...>, type_seq<Ts...>)
  28. {
  29. using namespace std; // workaround for a VC++ bug ('basic_string<...>' : undeclared identifier)
  30. return Variant(f(cast<Ts>(args[Is])...));
  31. }
  32.  
  33. template<typename F, typename... Ts>
  34. Variant invoke(F f, Variant* args, type_seq<Ts...> argTypes)
  35. {
  36. return invoke2(f, args, typename gen_num_seq<sizeof...(Ts)>::type(), argTypes);
  37. }
  38.  
  39. template<typename C, typename R, typename... A> auto get_arg_types_aux(R(C::*)(A...)) -> type_seq<A...>;
  40. template<typename C, typename R, typename... A> auto get_arg_types_aux(R(C::*)(A...) const) -> type_seq<A...>;
  41. template<typename R, typename... A> auto get_arg_types_aux(R(A...)) -> type_seq<A...>;
  42. template<typename R, typename... A> auto get_arg_types_aux(R(*)(A...)) -> type_seq<A...>;
  43. template<typename T> auto get_arg_types_aux(const T&) -> decltype(get_arg_types_aux(&T::operator()));
  44. template<typename F> auto get_arg_types(F&& f) -> decltype(get_arg_types_aux(f)) { return decltype(get_arg_types_aux(f))(); }
  45. }
  46.  
  47. template<typename F>
  48. Variant invoke(F f, Variant* args)
  49. {
  50. return details::invoke(f, args, details::get_arg_types(f));
  51. }
  52.  
  53. int main()
  54. {
  55. auto test = [](int a, double b, std::string c) -> int
  56. {
  57. std::cout << "a=" << a << '\n';
  58. std::cout << "b=" << b << '\n';
  59. std::cout << "c=" << c << '\n';
  60. return 42;
  61. };
  62.  
  63. Variant a[] = {Variant("20"), Variant("1.5"), Variant("x")};
  64. std::cout << cast<int>(invoke(test, a)) << '\n';
  65. }
  66.  
Success #stdin #stdout 0s 3072KB
stdin
Standard input is empty
stdout
a=20
b=1.5
c=x
42