fork download
  1. #include <typeinfo>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. template <typename typed, int i = 0> struct enumerate
  7. {
  8. static auto get(typed x) -> decltype(x.template get<i>()) { return x.template get<i>(); };
  9. const static bool has_next = !is_same<decltype(typed().template get<i+1>()), void>::value;
  10. typedef enumerate<typed, has_next?i+1:-1> next;
  11.  
  12. template <template <class> class handler> static void go(typed x)
  13. {
  14. handler<decltype(get(x))>()(get(x));
  15. if (has_next) next::template go<handler>(x);
  16. }
  17. };
  18.  
  19. template <typename typed> struct enumerate <typed, -1>
  20. {
  21. static void get(typed x) {}
  22. const static bool has_next = false;
  23. typedef enumerate<typed, -1> next;
  24.  
  25. template <template <class> class handler> static void go(typed x)
  26. {
  27. }
  28. };
  29.  
  30. #define ENUMERABLE_FIELD(type, name, i) public: type name; \
  31.   private: type get(key_t<i>) { return this->name; }
  32.  
  33. struct smth
  34. {
  35. private: template <int i> struct key_t {};
  36. private: template <int i> void get(key_t<i>) {}
  37.  
  38. ENUMERABLE_FIELD(int, x, 0)
  39. ENUMERABLE_FIELD(double, y, 1)
  40.  
  41. public: template <int i> auto get() -> decltype(this->get(key_t<i>())) { return this->get(key_t<i>()); }
  42. };
  43.  
  44. template <class typed> void print(const typed& t)
  45. {
  46. cout << t << endl;
  47. }
  48.  
  49. template <class typed> struct pass_to_print
  50. {
  51. void operator () (typed t) { return print(t); }
  52. };
  53.  
  54. int main()
  55. {
  56. smth s = {1, 2.5};
  57.  
  58. enumerate<smth>::go<pass_to_print>(s);
  59.  
  60. return 0;
  61. }
Success #stdin #stdout 0s 3468KB
stdin
Standard input is empty
stdout
1
2.5