 // Purpose.  Command and Memento        class Memento { public:
 //                                         Memento( int v ) { v_ = v; }
 // Discussion.  The left side uses a    private:
 // global stack of state frames to im-     friend class Number;
 // plement undo and redo of oper's on      int  v_;
 // Number objs.  The right side: pro-   };
 // motes to "full obj status" a re-
 // quest on a Number obj, encapsulates  class Number { public:
 // the rollback capability of Number       Number( int v ) { val_ = v; }
 // instances as a Memento, and main-       void incr()     { val_++; }
 // tains the stack of Commands and         void getVal()   { cout
 // Mementos in the Command class. Cli-        << "val is " << val_ << endl; }
 // ent complexity shrinks significant-     Memento* checkpt() {
 // ly, and flexibility soars.                 return new Memento( val_ ); }
                                            void rollback( Memento* m ) {
 class Number {                                val_ = m->v_ ; }
 public:                                 private:
    Number( int v )      { val_ = v; }      int val_;
    void incr()          { val_++;   }   };
    void setVal( int v ) { val_ = v; }
    int  getVal()     { return val_; }   class Command { public:
    void rptVal()     { cout                typedef void (Number::*Action)();
       << "val is " << val_ << endl; }      Command( Number* r, Action a ) {
 private:                                      rec_ = r;
    int val_;                                  act_ = a; }
 };                                         virtual void execute() {
                                               cmds_[num_] = this;
 struct Frame {                                mems_[num_] = rec_->checkpt();
    Number*  objPtr;                           num_++;
    void (Number::*funPtr)();                  (rec_->*act_)(); }
    int      state;                         static void undo() {
 };                                            cmds_[num_-1]->rec_->
                                                  rollback( mems_[num_-1] );
 Frame  stack[10];                             num_--; }
 int    ndx = 0;                            void static redo() {
                                               Number* r = cmds_[num_]->rec_;
 void undo() {                                 Action  a = cmds_[num_]->act_;
    ndx--;                                     (r->*a)();
    stack[ndx].objPtr->setVal(                 num_++; }
       stack[ndx].state );               private:
 }                                          Number*         rec_;
 void redo() {                              Action          act_;
    ((stack[ndx].objPtr)->*stack[ndx].      static Command* cmds_[20];
       funPtr)();                           static Memento* mems_[20];
    ndx++;                                  static int      num_;
 }                                       };
                                         Command* Command::cmds_[];
 void main( void )                       Memento* Command::mems_[];
 {                                       int      Command::num_ = 0;
    Number  one( 11 ), two( 22 );
                                         void main( void )
    stack[ndx].objPtr = &one;            {
    stack[ndx].funPtr = &Number::incr;      Number   one( 11 ), two( 22 );
    stack[ndx].state  = one.getVal();       Command  a( &one, &Number::incr );
    one.incr();  one.rptVal();  ndx++;      Command  b( &two, &Number::incr );
                                            a.execute();      one.getVal();
    stack[ndx].objPtr = &two;               b.execute();      two.getVal();
    stack[ndx].funPtr = &Number::incr;      Command::undo();  two.getVal();
    stack[ndx].state  = two.getVal();       Command::undo();  one.getVal();
    two.incr();  two.rptVal();  ndx++;      Command::redo();  one.getVal();
                                            Command::redo();  two.getVal();
    undo();      two.rptVal();           }
    undo();      one.rptVal();
    redo();      one.rptVal();           // val is 12     // val is 11
    redo();      two.rptVal();           // val is 23     // val is 12
 }                                       // val is 22     // val is 23

