//This is a little test program that demonstrates
//how to use our multiple dispatch library with
//the inheritance tree inference feature.

#include "infer_disp.hpp"


//Set up a class heirarchy, here we create the situation
//used in the example shown on the webpage. 
//(http://www.cs.swarthmore.edu/~bulnes/PL/lab1/index.html)
class A { public: virtual ~A() {} };
class A1 : public virtual A {};
class A2 : public virtual A {};
class A3 : public virtual A2, public virtual A1 {};
class A4 : public virtual A3, public virtual A2 {};


//create a couple of definitions of a function that
//takes two arguments, each of which can be cast to A.
int f(A *a, A *b)
{
  cout << "A,A" << endl;
  return 0;
}

int f(A2 *a, A *b)
{
  cout << "A2,A" << endl;
  return 0;
}

int f(A1 *a, A1  *b)
{
  cout << "A1,A1" << endl;
  return 0;
}

int f(A3 *a, A4  *b)
{
  cout << "A3,A4" << endl;
  return 0;
}

int main()
{
  //create the dispatcher object
  infer_disp<A,A,int> d(f);

  //register the functions that we want to dispatch between
  //with the dispatcher.
  //Rember that the order in which functions are added
  //determines the priority given to ansestors of the class.
  //(try switching the order of the next to lines to see
  //and example of this).
  d.add<A1,A1>(f); 
  d.add<A2,A>(f);
  d.add<A3,A4>(f);


  //Now we try a number of different dispatch combinations.
  
  A a;
  A1 a1;
  A2 a2;
  A3 a3;
  A4 a4;

  //print out the correct value, then make the dispatch call.
  cout << "A2,A:\t" ;
  d.dispatch(&a2,&a);

  cout << "A1,A1:\t" ;
  d.dispatch(&a1,&a1);

  cout << "A2,A:\t" ;
  d.dispatch(&a4,&a);

  cout << "A1,A1:\t" ;
  d.dispatch(&a4,&a1);

  cout << "A,A:\t" ;
  d.dispatch(&a1,&a2);

  cout << "A3,A4:\t" ;
  d.dispatch(&a3,&a4);

 
  return 0;
}
