Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 26.05.08 21:01
Оценка: 243 (25) :)))
По следам плодотворной дискусии про итераторы...

Используя идею "coroutines in C" Simon Tatham вот родилось следующее решение для C++.

Прежде всего пример генератора:


#include "generator.h"

generator(desc) 
{
   int i;
   emit(int) // будем выдавать int'ы
     for (i = 10; i > 0; --i)
       yield(i); // a.k.a. yield in Python - return next number in [10..1]
   stop(0); // все, конец последовательности.
};


При вызове оного "оператор" yield выдает следуещее число последовательности. Используется например так:

Пока есть следующее число печатаем его:

int main(int argc, char* argv[])
{
  desc gen;
  do
    printf("got number %d\n", gen());
  while (gen);
  return 0;
}


Вот весь исходник generator.h:


// generator/continuation for C++
// author: Andrew Fedoniouk @ terrainformatica.com
// idea borrowed from: "coroutines in C" Simon Tatham, 
//                     http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

#ifndef __generator_h_
#define __generator_h_

struct _generator
{
  int _line;
  _generator():_line(-1) {}
  operator bool() const { return _line != 0; }
};

#define generator(NAME) struct NAME : public _generator

#define emit(T)     T operator()() { \
                     if(_line < 0) { _line=0;}\
                     switch(_line) { case 0:;

#define stop(V)     } _line = 0; return (V); }

#define yield(V)     \
        do {\
            _line=__LINE__;\
            return (V); case __LINE__:;\
        } while (0)


#endif // __generator_h_


Вот другой пример: сканируем последовательность:


generator(backward) 
{
   int *head;
   int *tail;
   backward(int *start, int *end ): head(start), tail(end){}

   emit(int)
     while(--tail > head) 
         yield(*tail);
   stop(*tail);
};

int main(int argc, char* argv[])
{
  int arr[] = {1,2,3,4,5,6};
  backward scan(&arr[0],&arr[6]);
  do 
    printf("got number %d\n", scan());
  while(scan);
  return 0;
}


Вот такие вот пироги.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.