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

#include <simtemplatedvirtualfunc.h>
#include <visitorprint.h>
#include <visitorprint2.h>



class quat
{
public:

  double a;
  double x;
  double y;
  double z;

  quat(double _a, double _x, double _y, double _z)
    : a(_a), x(_x), y(_y), z(_z) {}

  ostream & print(ostream & os) const
    { return os << "<" << a << ",(" << x << "," << y <<"," << z << ")>"; }
};


ostream & operator << (ostream & os, quat const & q)
  { return q.print(os); }


string simtemplatedvirtualfunc::doc[] = 
{
  "",
  "Demo with visitorPrint function with many types.",
  "Demo of two templated virtual functions on the same data structures."
};



void simtemplatedvirtualfunc::test01()
{
  ElementA a;
  ElementB b;
  Element* e;
  cout << "Element A derived from Element" << endl;
  cout << "Element B derived from Element" << endl;

  e=&a;

  visitorPrint<int> pr(20);
//   cout << pr << endl;

  cout << "Let e point to an ElementA object" << endl;
  cout << "e->accept(pr)" << endl;
  e->accept(pr);

  cout << "e->accept( visitorPrint<int>(30) )" << endl;
  e->accept( visitorPrint<int>(30) );
  cout << "e->accept(visitorPrint<string>(\"hat mat cat\") )";
  e->accept( visitorPrint<string>("hat mat cat") );
  cout << "Let e point to a ElementB" << endl;
  e=&b;
  cout << "e->accept(pr)" << endl;
  e->accept(pr);
  cout << "e->accept( visitorPrint<int>(30) )" << endl;
  e->accept( visitorPrint<int>(30) );
  cout << "e->accept( visitorPrint<string>(\"hat mat cat\") )";
  e->accept( visitorPrint<string>("hat mat cat") );

  quat q1(1.0,2.0,-1.0,5.0);

  cout << "e->accept( visitorPrint<quat>(q1) ))";
  e->accept( visitorPrint<quat>(q1) );
  //cout << q1 << endl;


}

void simtemplatedvirtualfunc::test02()
{
  ElementA a;
  ElementB b;
  Element* e;
  
  quat q1(1.0,2.0,-1.0,5.0);
  e=&a;

  e->accept( visitorPrint<int>(30) );
  e->accept( visitorPrint<quat>(q1) );
  e->accept( visitorPrint<string>("hat mat cat") );


  e->accept( visitorPrint2<int>(30) );
  e->accept( visitorPrint2<quat>(q1) );
  e->accept( visitorPrint2<string>("hat mat cat") );
}




