 // Purpose.  Iterator                   #include <iostream.h>
 //
 // Discussion.  On the left, in order   class Stack {
 // to add an op== (without invading     public:
 // the production Stack code), two         friend class StackIter;
 // temporary Stack instances have to       Stack()  { sp_ = -1; }
 // be created, and then laboriously        void push( int in ) {
 // popped - this is too expensive.  On        items_[++sp_] = in; }
 // the right, a Stack with its partner     int pop() {
 // Iterator is a sufficient public in-        return items_[sp_--]; }
 // terface to efficiently add an op==      int isEmpty() {
 // without invading production code.          return (sp_ > -1) ? 0 : 1; }
                                            void tr() {
 #include <iostream.h>                         for (int i=0; i <= sp_; i++)
                                                  cout << items_[i] << ' ';
 class Stack {                                 cout << endl; }
 public:                                    StackIter* createIt();
    Stack() {                            private:
       sp_ = -1; }                          int  items_[10];
    void push( int in ) {                   int  sp_;
       items_[++sp_] = in; }             };
    int pop() {
       return items_[sp_--]; }           class StackIter {
    int isEmpty() {                      public:
       return (sp_ > -1) ? 0 : 1; }         StackIter( Stack* s ) { s_ = s; }
    void tr() {                             void first()   { index_ = 0; }
       for (int i=0; i <= sp_; i++)         void next()    { index_++; }
          cout << items_[i] << ' ';         int  isDone()  {
       cout << endl; }                         return index_ == s_->sp_+1; }
 private:                                   int  curr() {
    enum { SIZE = 10 };                        return s_->items_[index_]; }
    int  items_[SIZE];                   private:
    int  sp_;                               Stack*  s_;
 };                                         int     index_;
                                         };
 int operator==( Stack& l, Stack& r ) {
    Stack  tl(l), tr(r);                 StackIter* Stack::createIt() {
    while ( ! tl.isEmpty() )                return new StackIter( this ); }
       if (tl.pop() != tr.pop())
          break;                         int operator==( Stack& l, Stack& r ) {
    return (tl.isEmpty() &&                 StackIter*  itl = l.createIt();
            tr.isEmpty());                  StackIter*  itr = r.createIt();
 }                                          for ( itl->first(), itr->first();
                                                  ! itl->isDone();
 void main( void )                                itl->next(), itr->next())
 {                                             if (itl->curr() != itr->curr())
    Stack  s1, s2, s3, s4;   int  i;              break;
    for (i=1; i < 5; i++) s1.push(i);       int ans = itl->isDone() &&
    for (i=1; i < 5; i++) s2.push(i);                 itr->isDone();
    for (i=1; i < 6; i++) s3.push(i);       delete itl;   delete itr;
    for (i=1; i < 4; i++) s4.push(i);       return ans; }
    s4.push(2);
    s1.tr(); s2.tr(); s3.tr(); s4.tr();  void main( void )
    cout << "2 is "<< (s1==s2) << endl;  {
    cout << "3 is "<< (s1==s3) << endl;     Stack  s1, s2, s3, s4;   int  i;
    cout << "4 is "<< (s1==s4) << endl;     for (i=1; i < 5; i++) s1.push(i);
 }                                          for (i=1; i < 5; i++) s2.push(i);
                                            for (i=1; i < 6; i++) s3.push(i);
 // 1 2 3 4                                 for (i=1; i < 4; i++) s4.push(i);
 // 1 2 3 4                                 s4.push(2);
 // 1 2 3 4 5                               s1.tr(); s2.tr(); s3.tr(); s4.tr();
 // 1 2 3 2                                 cout << "2 is "<< (s1==s2) << endl;
 // 2 is 1                                  cout << "3 is "<< (s1==s3) << endl;
 // 3 is 0                                  cout << "4 is "<< (s1==s4) << endl;
 // 4 is 0                               }

