fork download
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. #define CONCAT2(x, y) x ## y
  5. #define CONCAT(x, y) CONCAT2(x, y)
  6.  
  7. #ifdef _WIN32
  8.  
  9. #define GET_LABEL_PTR(p, label)\
  10.   {\
  11.   void* _theLabelPointer;\
  12.   __asm { mov [_theLabelPointer], offset label }\
  13.   p = _theLabelPointer;\
  14.   }
  15.  
  16. #define JUMP_TO_LABEL(p)\
  17.   {\
  18.   void* _theLabelPointer = p;\
  19.   __asm { jmp _theLabelPointer }\
  20.   }
  21.  
  22. #else // _WIN32
  23.  
  24. #define GET_LABEL_PTR(p, label) p = &&label;
  25.  
  26. #define JUMP_TO_LABEL(p) goto *p;
  27.  
  28. #endif // _WIN32
  29.  
  30. #define YIELD2(val,counter)\
  31.   {\
  32.   GET_LABEL_PTR(_p, CONCAT(YIELD,counter));\
  33.   i = (val);\
  34.   return i;\
  35.   CONCAT(YIELD,counter): ;\
  36.   }
  37.  
  38. #define YIELD(val) YIELD2(val,__COUNTER__)
  39.  
  40. #define RETURN { _ended = true; return i; }
  41.  
  42. #define DEF_ITER(ret_type, name, state_vars, code) \
  43.   struct name \
  44.   {\
  45.   state_vars;\
  46.   ret_type i;\
  47.   bool _ended; void* _p;\
  48.   name() : _ended(false), _p(0) {}\
  49.   bool ended() const { return _ended; }\
  50.   operator bool() { next(); return !_ended; }\
  51.   ret_type next()\
  52.   {\
  53.   if (_ended) { throw(0); return i; }\
  54.   if (_p)\
  55.   JUMP_TO_LABEL(_p);\
  56.   code;\
  57.   \
  58.   _ended = true;\
  59.   return i;\
  60.   }\
  61.   };
  62.  
  63. // Test iterators
  64.  
  65. DEF_ITER(int, get57, ,
  66. YIELD(5);
  67. YIELD(7);
  68. RETURN;
  69. YIELD(42); // Should not happen
  70. )
  71.  
  72. DEF_ITER(int, fibos, int a;int b,
  73. a = 1;
  74. b = 1;
  75. for (;;)
  76. {
  77. YIELD(a);
  78. std::swap(a, b);
  79. b += a;
  80. }
  81. )
  82.  
  83. DEF_ITER(int, range, int start;int end,
  84. while (start < end)
  85. {
  86. YIELD(start);
  87. ++start;
  88. }
  89. )
  90.  
  91. DEF_ITER(int, range_recurse, int start; int end; std::unique_ptr<range_recurse> r,
  92. r = NULL;
  93.  
  94. if (start >= end)
  95. RETURN;
  96.  
  97. YIELD(start);
  98. r.reset(new range_recurse);
  99. r->start = start + 1;
  100. r->end = end;
  101. while (*r)
  102. YIELD(r->i);
  103. )
  104.  
  105. DEF_ITER(int, n_fibos, int count; fibos f; range r,
  106. r.start = 0;
  107. r.end = count;
  108. while (r)
  109. YIELD(f.next());
  110. )
  111.  
  112. int main(int argc, char* argv[])
  113. {
  114. {
  115. std::cout << "*** 5 fibos" << std::endl;
  116. n_fibos s;
  117. s.count = 5;
  118. while (s)
  119. std::cout << s.i << std::endl;
  120. }
  121.  
  122. {
  123. std::cout << "\n*** fibos < 20" << std::endl;
  124. fibos s;
  125. while (s && s.i < 20)
  126. std::cout << s.i << std::endl;
  127. }
  128.  
  129. {
  130. std::cout << "\n*** 5 and 7" << std::endl;
  131. get57 s;
  132. while (s)
  133. std::cout << s.i << std::endl;
  134. }
  135.  
  136. {
  137. std::cout << "\n*** 4..7" << std::endl;
  138. range s; s.start = 4; s.end = 8;
  139. while (s)
  140. std::cout << s.i << std::endl;
  141. }
  142.  
  143. {
  144. std::cout << "\n*** 10..14" << std::endl;
  145. range_recurse s; s.start = 10; s.end = 15;
  146. while (s)
  147. std::cout << s.i << std::endl;
  148. }
  149. return 0;
  150. }
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
*** 5 fibos
1
1
2
3
5

*** fibos < 20
1
1
2
3
5
8
13

*** 5 and 7
5
7

*** 4..7
4
5
6
7

*** 10..14
10
11
12
13
14