// Purpose.  Visitor (adding ops)       #include <iostream.h>
//                                      class Visitor;
// Discussion.  On the left, adding
// new operations requires modifying    class Color { public:
// all the current Color classes.  If      virtual void accept( Visitor& ) = 0;
// we introduce an extra level of in-   };
// direction (a Visitor hierarchy),
// then operations capable of opera-    class Red : public Color { public:
// ting on Color classes can be added      void accept( Visitor& );
// without modifying any existing          void eye() { cout << "Red::eye\n"; }
// code.  On the right, an entry point  };
// for all future operations has been   class Blu : public Color { public:
// added in the form of the accept()       void accept( Visitor& );
// method.  Each of the previous op-       void sky() { cout << "Blu::sky\n"; }
// erations has been encapsulated in    };
// its own derived Visitor class.  Any
// new operations simply require the    class Visitor { public:
// addition of a new Visitor class.        virtual void visit( Red& ) = 0;
//                                         virtual void visit( Blu& ) = 0;
// When we call accept() on a Color     };
// object, dynamic binding gets us to
// the correct derived class of Color.  class CountV : public Visitor {
// Then when we call visit() on the     public:
// Visitor object, dynamic binding         CountV() { numRed_ = numBlu_ = 0; }
// gets us to the correct derived          virtual void visit( Red& ) {
// class of Visitor.  [Visitors and           numRed_++; }
// Colors can be passed by address or      virtual void visit( Blu& ) {
// passed by reference.]                      numBlu_++; }
                                           void reportNum() {
#include <iostream.h>                         cout << "Reds " << numRed_ <<
                                              ", Blus " << numBlu_ << endl; }
class Color {                           private:
public:                                    int  numRed_, numBlu_;
   virtual void count() = 0;            };
   virtual void call()  = 0;
   static void reportNum() {            class CallV : public Visitor { public:
      cout << "Reds " << numRed_ <<        virtual void visit( Red& r ) {
      ", Blus " << numBlu_ <<endl; }          r.eye(); }
protected:                                 virtual void visit( Blu& b ) {
   static int numRed_, numBlu_;               b.sky(); }
};                                      };
int Color::numRed_ = 0;
int Color::numBlu_ = 0;                 void Red::accept( Visitor& v ) {
                                           v.visit( *this ); }
class Red : public Color { public:      void Blu::accept( Visitor& v ) {
   void count() { numRed_++; }             v.visit( *this ); }
   void call() { eye(); }
   void eye() { cout << "Red::eye\n";}  void main( void )
};                                      {
                                           Color* set[] = { new Red, new Blu,
class Blu : public Color { public:            new Blu, new Red, new Red, 0 };
   void count() { numBlu_++; }             CountV  countOp;
   void call() { sky(); }                  CallV   callOp;
   void sky() { cout << "Blu::sky\n";}     for (int i=0; set[i]; i++) {
};                                            set[i]->accept( countOp );
                                              set[i]->accept( callOp ); }
void main( void )                           countOp.reportNum();
{                                       }
   Color* set[] = { new Red, new Blu,
      new Blu, new Red, new Red, 0 };   // Red::eye
   for (int i=0; set[i]; i++) {         // Blu::sky
      set[i]->count();                  // Blu::sky
      set[i]->call(); }                 // Red::eye
    Color::reportNum();                 // Red::eye
}                                       // Reds 3, Blus 2




// Purpose.  Visitor (double dispatch)
//
// Discussion.  On the left, the State derived classes must query the type of
// the Cmd objects they receive, in order to identify what the next course of
// action is.  "case" stmts are always a maintenance headache.  On the right,
// we have recognized that what we really want to do is "dispatch" based on
// the type of TWO objects, (a State object and a Cmd object).  The call to
// accept() discriminates the type of the State object that is being messaged,
// and then the call to visit() discriminates the type of the Cmd object
// (while passing the type of the State object).  If new Cmd classes are
// added, no change whatsoever is necessary in the code of the State classes.
// If new State classes are added, then every Cmd class must be changed, and
// Visitor is NOT the right approach to take.

#include <iostream.h>                   #include <iostream.h>
int  current = 0;                       int  current = 0;
enum CmdTyp { OnT, OffT };              class One;  class Two;

class Cmd { public:                     class Cmd { public:
   virtual CmdTyp typ() = 0;               virtual void visit( One* ) {
};                                            cout << "ERROR\n"; }
class On : public Cmd { public:            virtual void visit( Two* ) {
   CmdTyp typ() { return OnT; }               cout << "ERROR\n"; }
};                                      };
class Off : public Cmd { public:        class On : public Cmd { public:
   CmdTyp typ() { return OffT; }           void visit( One* ) {
};                                            current = 1;
                                              cout << "One,On => Two\n"; }
class State { public:                      void visit( Two* t ) {
   virtual void process( Cmd* c ) {           Cmd::visit( t ); }
      cout << "ERROR\n"; }              };
};                                      class Off : public Cmd { public:
class One : public State { public:         void visit( One* o ) {
   void process( Cmd* c ) {                   Cmd::visit( o ); }
      if (c->typ() == OnT) {               void visit( Two* ) {
         current = 1;                         current = 0;
         cout << "One,On => Two\n"; }         cout << "Two,Off => One\n"; }
      else if (c->typ() == OffT)        };
         State::process( c );
   }                                    class State { public:
};                                         virtual void accept( Cmd* c ) = 0;
class Two : public State { public:      };
   void process( Cmd* c ) {             class One : public State { public:
      if (c->typ() == OnT)                 void accept( Cmd* c ) {
         State::process( c );                 c->visit( this ); }
      else if (c->typ() == OffT) {      };
         current = 0;                   class Two : public State { public:
         cout << "Two,Off => One\n"; }     void accept( Cmd* c ) {
   }                                          c->visit( this ); }
};                                      };

State* states[] = { new One, new Two }; State* states[] = { new One, new Two };

void main( void )                       void main( void )
{                                       {
   Cmd* c[] = { new Off,                   Cmd* c[] = { new Off,
        new On, new Off, new Off, 0 };          new On, new Off, new Off, 0 };
   for (int i=0; c[i]; i++)                for (int i=0; c[i]; i++)
      states[current]->process( c[i] );       states[current]->accept( c[i] );
}                                       }

// ERROR                                // ERROR
// One,On => Two                        // One,On => Two
// Two,Off => One                       // Two,Off => One
// ERROR                                // ERROR




// Purpose.  Visitor design pattern

// 1. Add an accept(Visitor) method to the "element" hierarchy
// 2. Create a "visitor" base class w/ a visit() method for every "element" type
// 3. Create a "visitor" derived class for each "operation" to do on "elements"
// 4. Client creates "visitor" objects and passes each to accept() calls

#include <iostream>
#include <string>
using namespace std;

// 1. Add an accept(Visitor) method to the "element" hierarchy
class Element { public:
   virtual void accept( class Visitor& v ) = 0;
};

class This : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string thiss() { return "This"; }
};

class That : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string that() { return "That"; }
};

class TheOther : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string theOther() { return "TheOther"; }
};

// 2. Create a "visitor" base class w/ a visit() method for every "element" type
class Visitor { public:
   virtual void visit( This* e ) = 0;
   virtual void visit( That* e ) = 0;
   virtual void visit( TheOther* e ) = 0;
};

/*virtual*/ void This::accept( Visitor& v )     { v.visit( this ); }
/*virtual*/ void That::accept( Visitor& v )     { v.visit( this ); }
/*virtual*/ void TheOther::accept( Visitor& v ) { v.visit( this ); }

// 3. Create a "visitor" derived class for each "operation" to do on "elements"
class UpVisitor : public Visitor {
   /*virtual*/ void visit( This* e ) {
      cout << "do Up on " + e->thiss() << '\n'; }
   /*virtual*/ void visit( That* e ) {
      cout << "do Up on " + e->that() << '\n'; }
   /*virtual*/ void visit( TheOther* e ) {
      cout << "do Up on " + e->theOther() << '\n'; }
};

class DownVisitor : public Visitor {
   /*virtual*/ void visit( This* e ) {
      cout << "do Down on " + e->thiss() << '\n'; }
   /*virtual*/ void visit( That* e ) {
      cout << "do Down on " + e->that() << '\n'; }
   /*virtual*/ void visit( TheOther* e ) {
      cout << "do Down on " + e->theOther() << '\n'; }
};

void main( void ) {
   Element* list[] = { new This(), new That(), new TheOther() };
   UpVisitor    up;             // 4. Client creates
   DownVisitor  down;           //    "visitor" objects
   for (int i=0; i < 3; i++)    //    and passes each
      list[i]->accept( up );    //    to accept() calls
   for (i=0; i < 3; i++)
      list[i]->accept( down );
}

// do Up on This                // do Down on This
// do Up on That                // do Down on That
// do Up on TheOther            // do Down on TheOther




// Purpose.  Visitor - recovering lost type information
//
// Motivation.  "My Component classes do not know that Composites exist.
// They provide no help for navigating Composites, nor any help for
// altering the contents of a Composite.  This is because I would like the
// base class (and all its derivatives) to be reusable in contexts that do
// not require Composites.  When given a base class pointer, if I
// absolutely need to know whether or not it is a Composite, I will use
// dynamic_cast() to figure this out.  In those cases where dynamic_cast()
// is too expensive, I will use a Visitor." [Robert Martin]

#include <iostream>
#include <vector>
using namespace std;

class Visitor { public:
   virtual void visit( class Primitive*, class Component* ) = 0;
   virtual void visit( class Composite*, Component* ) = 0;
};

class Component {
   int value;
public:
   Component( int val )    { value = val; }
   virtual void traverse() { cout << value << " "; }
   // Having add() here sacrifices safety, but it supports transparency
   // virtual void add( Component* ) { }
   virtual void accept( Visitor&, Component* ) = 0;
};

class Primitive : public Component { public:
   Primitive( int val ) : Component( val ) { }
   /*virtual*/ void accept( Visitor& v, Component* c ) { v.visit( this, c ); }
};

class Composite : public Component {
   vector<Component*> children;
public:
   Composite( int val ) : Component( val ) { }
   void add( Component* ele ) { children.push_back( ele ); }
   /*virtual*/ void accept( Visitor& v, Component* c ) { v.visit( this, c ); }
   /*virtual*/ void traverse() {
      Component::traverse();
      for (int i=0; i < children.size(); i++)
         children[i]->traverse();
}  };

class AddVisitor : public Visitor { public:
   /*virtual*/ void visit( Primitive*, Component* ) {/* does not make sense */}
   /*virtual*/ void visit( Composite* node, Component* c ) { node->add( c ); }
};

void main( void ) {
   Component*  nodes[3];
   // The type of Composite* is "lost" when the object is assigned to a
   // Component*
   nodes[0] = new Composite(1);
   nodes[1] = new Composite(2);
   nodes[2] = new Composite(3);

   // If add() were in class Component, this would work
   //    nodes[0]->add( nodes[1] );
   // If it is NOT in Component, and only in Composite,  you get the error -
   //    no member function `Component::add(Component *)' defined

   // Instead of sacrificing safety, we use a Visitor to support add()
   AddVisitor  addVisitor;
   nodes[0]->accept( addVisitor, nodes[1] );
   nodes[0]->accept( addVisitor, nodes[2] );
   nodes[0]->accept( addVisitor, new Primitive(4) );
   nodes[1]->accept( addVisitor, new Primitive(5) );
   nodes[1]->accept( addVisitor, new Primitive(6) );
   nodes[2]->accept( addVisitor, new Primitive(7) );
       
   for (int i=0; i < 3; i++) {
      nodes[i]->traverse();
      cout << endl;
}  }

// 1 2 5 6 3 7 4
// 2 5 6
// 3 7




// Purpose.  Combining Visitor with Composite's recursive traversal

#include <iostream>
#include <vector>
using namespace std;

class Visitor { public:
   virtual void visit( class Leaf* e )      = 0;
   virtual void visit( class Composite* e ) = 0;
};

class Component { public:
   virtual void traverse() = 0;
   virtual void accept( class Visitor& v ) = 0;
};

class Leaf : public Component {
   int value;
public:
   Leaf( int val ) { value = val; }
   /*virtual*/ void traverse() { cout << value << ' '; }
   /*virtual*/ void accept( class Visitor& v ) { v.visit( this ); }
   int getValue() { return value; }
};

class Composite : public Component {
   char value;
   vector<Component*> children;
   static char next;
public:
   Composite() { value = next++; }
   void add( Component* ele ) { children.push_back( ele ); }
   /*virtual*/ void traverse() {
      cout << value << ' ';
      for (int i=0; i < children.size(); i++)
         children[i]->traverse();
   }
   /*virtual*/ void accept( class Visitor& v ) {
      v.visit( this );
      // accept() has been embellished to include the logic in traverse()
      for (int i=0; i < children.size(); i++)
         children[i]->accept( v );
   }
   char getValue() { return value; }
};
char Composite::next = 'a';

class TransformVisitor : public Visitor { public:
   /*virtual*/ void visit( Leaf* e ) { cout << e->getValue() + 100 << ' '; }
   /*virtual*/ void visit( Composite* e ) { cout << (char)(e->getValue()-32) <<' ';}
};

void main( void ) {
   Composite containers[4];
   for (int i=0; i < 4; i++)
      for (int j=0; j < 3; j++)
         containers[i].add( new Leaf( i * 3 + j ) );
   for (i=1; i < 4; i++) containers[0].add( &(containers[i]) );

   containers[0].traverse();   cout << endl;

   TransformVisitor tv;
   // don't need an "iteration" capability with this design
   containers[0].accept( tv );   cout << endl;
}

// a 0 1 2 b 3 4 5 c 6 7 8 d 9 10 11
// A 100 101 102 B 103 104 105 C 106 107 108 D 109 110 111




// Purpose.  Undesireable design - double dispatch - doing the right thing based
// on the type of two objects

#include <iostream>
#include <string>
using namespace std;

class Request { public: virtual string getType() = 0; };

class R1 : public Request { public:
   /*virtual*/ string getType() { return "One"; }
   void reqOneMethod( class P1* );
   void reqOneMethod( class P2* );
};
class R2 : public Request { public:
   /*virtual*/ string getType() { return "Two"; }
   void reqTwoMethod( P1* );
   void reqTwoMethod( P2* );
};

class Processor { public: virtual void handle( class Request* ) = 0; };

class P1 : public Processor { public:
   /*virtual*/ void handle( class Request* req ) {
      if (req->getType() == string("One"))      ((R1*)req)->reqOneMethod( this );
      else if (req->getType() == string("Two")) ((R2*)req)->reqTwoMethod( this );
   }
   void procOneMethod() { cout << "processor one handling "; }
};
class P2 : public Processor { public:
   /*virtual*/ void handle( class Request* req ) {
      if (req->getType() == string("One"))      ((R1*)req)->reqOneMethod( this );
      else if (req->getType() == string("Two")) ((R2*)req)->reqTwoMethod( this );
   }
   void procTwoMethod() { cout << "processor two handling "; }
};

void R1::reqOneMethod( P1* p ) { p->procOneMethod(); cout << "request one\n"; }
void R1::reqOneMethod( P2* p ) { p->procTwoMethod(); cout << "request one\n"; }
void R2::reqTwoMethod( P1* p ) { p->procOneMethod(); cout << "request two\n"; }
void R2::reqTwoMethod( P2* p ) { p->procTwoMethod(); cout << "request two\n"; }

void main( void ) {
   Processor* handlers[] = { new P1(), new P2() };
   Request*   commands[] = { new R1(), new R2() };
   for (int i=0; i < 2; i++)
      for (int j=0; j < 2; j++)
         handlers[i]->handle( commands[j] );
}

// processor one handling request one
// processor one handling request two
// processor two handling request one
// processor two handling request two




// Purpose.  Visitor - double dispatch - doing the right thing based on the
// type of two objects

#include <iostream>
#include <string>
using namespace std;

class Request { public:
   // second dispatch - the "visit()" method
   virtual void execute( class P1* ) = 0;
   virtual void execute( class P2* ) = 0;
};
class R1 : public Request { public:
   /*virtual*/ void execute( P1* );
   /*virtual*/ void execute( P2* );
};
class R2 : public Request { public:
   /*virtual*/ void execute( P1* );
   /*virtual*/ void execute( P2* );
};

class Processor { public:
   // first dispatch - the "accept()" method
   virtual void handle( class Request* ) = 0;
};
class P1 : public Processor { public:
   /*virtual*/ void handle( Request* req ) { req->execute( this ); }
   void procOneMethod() { cout << "processor one handling "; }
};
class P2 : public Processor { public:
   /*virtual*/ void handle( Request* req ) { req->execute( this ); }
   void procTwoMethod() { cout << "processor two handling "; }
};

/*virtual*/ void R1::execute( P1* p ) { p->procOneMethod(); cout << "request one\n"; }
/*virtual*/ void R1::execute( P2* p ) { p->procTwoMethod(); cout << "request one\n"; }
/*virtual*/ void R2::execute( P1* p ) { p->procOneMethod(); cout << "request two\n"; }
/*virtual*/ void R2::execute( P2* p ) { p->procTwoMethod(); cout << "request two\n"; }

void main( void ) {
   Processor* handlers[] = { new P1(), new P2() };
   Request*   commands[] = { new R1(), new R2() };
   for (int i=0; i < 2; i++)
      for (int j=0; j < 2; j++)
         handlers[i]->handle( commands[j] );
}

// processor one handling request one
// processor one handling request two
// processor two handling request one
// processor two handling request two




// Purpose.  Acyclic Visitor design pattern [PLOPD vol 3, p93]
//
// Problem.  In GOF Visitor, Element depends on Visitor, Visitor depends on
// all Element derivatives, and Element derivatives depend on Element; this is
// cyclic dependency.  Additionally, adding an Element derivative requires the
// entire Visitor hierarchy to change.  "These problems can be solved by using
// multiple inheritance and dynamic_cast()."
//
// Solution.  Element derived classes are only coupled to Visitor base class.
// Visitor derived classes are only coupled to the Element derived classes that
// they choose to be coupled to.  If a new Element derived class is added,
// Visitor derived classes can update themselves if, and when, they choose.

#include <iostream>
#include <string>
using namespace std;

class Element { public:
   virtual void accept( class Visitor& v ) = 0;
};

class This : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string thiss() { return "This"; }
};

class That : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string that() { return "That"; }
};

class TheOther : public Element { public:
   /*virtual*/ void accept( Visitor& v );
   string theOther() { return "TheOther"; }
};

class Visitor { public:
   virtual ~Visitor() { };
};
class ThisVisitor { public:
   virtual void visit( This* e ) = 0;
};
class ThatVisitor { public:
   virtual void visit( That* e ) = 0;
};
class TheOtherVisitor { public:
   virtual void visit( TheOther* e ) = 0;
};

/*virtual*/ void This::accept( Visitor& v ) {
   ThisVisitor* tv = dynamic_cast<ThisVisitor*>( &v );
   if (tv) tv->visit( this );
   else cout << "the visitor was not accepted\n";
}
/*virtual*/ void That::accept( Visitor& v ) {
   ThatVisitor* tv = dynamic_cast<ThatVisitor*>( &v );
   if (tv) tv->visit( this );
   else cout << "the visitor was not accepted\n";
}
/*virtual*/ void TheOther::accept( Visitor& v ) {
   TheOtherVisitor* tv = dynamic_cast<TheOtherVisitor*>( &v );
   if (tv) tv->visit( this );
   else cout << "the visitor was not accepted\n";
}

class UpVisitor : public Visitor, public ThisVisitor, public ThatVisitor,
      public TheOtherVisitor {
   /*virtual*/ void visit( This* e ) {
      cout << "do Up on " + e->thiss() << '\n'; }
   /*virtual*/ void visit( That* e ) {
      cout << "do Up on " + e->that() << '\n'; }
   /*virtual*/ void visit( TheOther* e ) {
      cout << "do Up on " + e->theOther() << '\n'; }
};

class DownVisitor : public Visitor, public ThisVisitor, public ThatVisitor,
      public TheOtherVisitor {
   /*virtual*/ void visit( This* e ) {
      cout << "do Down on " + e->thiss() << '\n'; }
   /*virtual*/ void visit( That* e ) {
      cout << "do Down on " + e->that() << '\n'; }
   /*virtual*/ void visit( TheOther* e ) {
      cout << "do Down on " + e->theOther() << '\n'; }
};

void main( void ) {
   Element* list[] = { new This(), new That(), new TheOther() };
   UpVisitor    up;             // 4. Client creates
   DownVisitor  down;           //    "visitor" objects
   for (int i=0; i < 3; i++)    //    and passes each
      list[i]->accept( up );    //    to accept() calls
   for (i=0; i < 3; i++)
      list[i]->accept( down );
}

// do Up on This                // do Down on This
// do Up on That                // do Down on That
// do Up on TheOther            // do Down on TheOther




// Purpose.  Double dispatch (within a single hierarchy)
//
// Discussion.  We would like to declare a function like:
//    void process( virtual Base* object1, virtual Base* object2 )
// that does the right thing based on the type of 2 objects that come from
// a single inheritance hierarchy.  The only problem is that the keyword
// "virtual" may not be used to request dynamic binding for an object being
// passed as an argument.  C++ will only "discriminate" the type of an object
// being messaged, not the type of an object being passed.  So in order for
// the type of 2 objects to be discriminated, each object must be the
// receiver of a virtual function call.  Here, when process1() is called on
// the first object, its type becomes "known" at runtime, but the type of
// the second is still UNknown.  process2() is then called on the second
// object, and the identity (and type) of the first object is passed as an
// argument.  Flow of control has now been vectored to the spot where the
// type (and identity) of both objects are known.

#include <iostream>
using namespace std;

class Base { public:
   virtual void process1( Base& ) = 0;
   virtual void process2( class A& ) = 0;
   virtual void process2( class B& ) = 0;
   virtual void process2( class C& ) = 0;
};

class A : public Base { public:
   /*virtual*/ void process1( Base& second ) { second.process2( *this ); }
   /*virtual*/ void process2( class A& first ) {
      cout << "first is A, second is A\n"; }
   /*virtual*/ void process2( class B& first ) {
      cout << "first is B, second is A\n"; }
   /*virtual*/ void process2( class C& first ) {
      cout << "first is C, second is A\n"; }
};

class B : public Base { public:
   /*virtual*/ void process1( Base& second ) { second.process2( *this ); }
   /*virtual*/ void process2( class A& first ) {
      cout << "first is A, second is B\n"; }
   /*virtual*/ void process2( class B& first ) {
      cout << "first is B, second is B\n"; }
   /*virtual*/ void process2( class C& first ) {
      cout << "first is C, second is B\n"; }
};

class C : public Base { public:
   /*virtual*/ void process1( Base& second ) { second.process2( *this ); }
   /*virtual*/ void process2( class A& first ) {
      cout << "first is A, second is C\n"; }
   /*virtual*/ void process2( class B& first ) {
      cout << "first is B, second is C\n"; }
   /*virtual*/ void process2( class C& first ) {
      cout << "first is C, second is C\n"; }
};

void main( void ) {
   Base* array[] = { &A(), &B(), &C() };
   for (int i=0; i < 3; i++)
      for (int j=0; j < 3; j++)
         array[i]->process1( *array[j] );
}

// first is A, second is A
// first is A, second is B
// first is A, second is C
// first is B, second is A
// first is B, second is B
// first is B, second is C
// first is C, second is A
// first is C, second is B
// first is C, second is C




// Purpose.  Triple dispatch (within a single hierarchy)
//
// Discussion.  It would be nice if C++ supported creating a function like:
// "processCombine( virtual Binary& first, virtual Binary& second, virtual
// Binary& third )".  While not directly supported, we can simulate this kind
// of capability by: calling combine() on the first object to resolve its
// type, then calling combine() on the second object to resolve its type,
// then calling combine() on the third object to resolve its type.  We
// "remember" the type information we have "discriminated" at each stage by
// juggling the three objects through 2 increasingly type-specific parameter
// slots.

#include <iostream>
using namespace std;

class Zero;
class One;

class Binary {
public:
   // First dispatch
   virtual void combine( Binary& second, Binary& third ) = 0;

   // Second dispatch
   virtual void combine( Binary& third, Zero& first ) = 0;
   virtual void combine( Binary& third, One&  first ) = 0;

   // Third dispatch
   virtual void combine( Zero& first, Zero& second ) = 0;
   virtual void combine( Zero& first, One&  second ) = 0;
   virtual void combine( One& first,  Zero& second ) = 0;
   virtual void combine( One& first,  One&  second ) = 0;
};

class Zero : public Binary {
public:
   void combine( Binary& second, Binary& third ) {
      second.combine( third, *this ); }

   void combine( Binary& third, Zero& first ) {
      third.combine( first, *this ); }
   void combine( Binary& third, One& first ) {
      third.combine( first, *this ); }

   void combine( Zero& first, Zero& second );
   void combine( Zero& first, One&  second );
   void combine( One&  first, Zero& second );
   void combine( One&  first, One&  second );

   void doZero() { cout << "0  "; }
};

class One : public Binary {
public:
   void combine( Binary& second, Binary& third ) {
      second.combine( third, *this ); }

   void combine( Binary& third, Zero& first ) {
      third.combine( first, *this ); }
   void combine( Binary& third, One& first ) {
      third.combine( first, *this ); }

   void combine( Zero& first, Zero& second );
   void combine( Zero& first, One&  second );
   void combine( One&  first, Zero& second );
   void combine( One&  first, One&  second );

   void doOne() { cout << "1  "; }
};

void Zero::combine( Zero& first, Zero& second ) {
   first.doZero();  second.doZero();  doZero();  cout << endl; }
void Zero::combine( Zero& first, One&  second ) {
   first.doZero();  second.doOne();   doZero();  cout << endl; }
void Zero::combine( One&  first, Zero& second ) {
   first.doOne();   second.doZero();  doZero();  cout << endl; }
void Zero::combine( One&  first, One&  second ) {
   first.doOne();   second.doOne();   doZero();  cout << endl; }

void One::combine( Zero& first, Zero& second ) {
   first.doZero();  second.doZero();  doOne();  cout << endl; }
void One::combine( Zero& first, One&  second ) {
   first.doZero();  second.doOne();   doOne();  cout << endl; }
void One::combine( One&  first, Zero& second ) {
   first.doOne();   second.doZero();  doOne();  cout << endl; }
void One::combine( One&  first, One&  second ) {
   first.doOne();   second.doOne();   doOne();  cout << endl; }

void processCombine( Binary& first, Binary& second, Binary& third ) {
   first.combine( second, third );
}

void main( void ) {
   Binary*  list[2] = { &Zero(), &One() };

   // Run through permutations
   for (int i=0; i < 2; i++)
      for (int j=0; j < 2; j++)
         for (int k=0; k < 2; k++)
            processCombine( *list[i], *list[j], *list[k] );
}

// 0  0  0 
// 0  0  1 
// 0  1  0 
// 0  1  1 
// 1  0  0 
// 1  0  1 
// 1  1  0 
// 1  1  1