fork(1) download
  1. #include <typeinfo>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. template <typename typed, int i = 1> 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:0> 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, 0>
  20. {
  21. static void get(typed x) {}
  22. const static bool has_next = false;
  23. typedef enumerate<typed, 0> next;
  24.  
  25. template <template <class> class handler> static void go(typed x)
  26. {
  27. }
  28. };
  29.  
  30. struct smth
  31. {
  32. template <int i> struct key_t {};
  33.  
  34. template <int i> void get(key_t<i>) {}
  35.  
  36. int x; int get(key_t<1>) { return this->x; }
  37. double y; double get(key_t<2>) { return this->y; }
  38.  
  39. template <int i> auto get() -> decltype(this->get(key_t<i>())) { return this->get(key_t<i>()); }
  40. };
  41.  
  42. template <class typed> void print(const typed& t)
  43. {
  44. cout << t << endl;
  45. }
  46.  
  47. template <class typed> struct pass_to_print
  48. {
  49. void operator () (typed t) { return print(t); }
  50. };
  51.  
  52. int main()
  53. {
  54. smth s = {1, 2.5};
  55.  
  56. cout.setf(ios::boolalpha);
  57.  
  58. cout << s.x << ' ' << s.y << endl;
  59. cout << s.get<1>() << ' ' << s.get<2>() << endl;
  60. cout << endl;
  61.  
  62. cout << enumerate<smth, 1>::get(s) << ' ' << enumerate<smth, 1>::has_next << endl;
  63. cout << enumerate<smth, 1>::next::get(s) << ' ' << enumerate<smth, 1>::next::has_next << endl;
  64. cout << endl;
  65.  
  66. enumerate<smth>::go<pass_to_print>(s);
  67.  
  68. return 0;
  69. }
Success #stdin #stdout 0s 3468KB
stdin
Standard input is empty
stdout
1 2.5
1 2.5

1 true
2.5 false

1
2.5