#include <cstdlib>

#include <iostream>
#include <string>
#include <list>

#include "Triple-soln.h"
#include "Point3D-soln.h"

using namespace std;

// XXX error: '>>' should be '> >' within a nested template
//   (Without context, this is ambiguous between the shift operator
//    and two ending brackets for a nested template)
// XXX error: 'triples' was not declared in this scope
//   (A cascading result from the previous error)
// XXX error: expected initializer before ‘int’
//   (Caused by the seemingly innocuous missing semi-colon.  This used
//    to be one of the errors that would occur from missing a
//    semi-colon at the end of a class declaration.)
template <class T1, class T2, class T3>
void PrintTriples(const list<Triple<T1,T2,T3> > triples);

int main(int argc, char *argv[]) {
  Point3D p1(3,1,5);
  Point3D p2(-101,100,3);
  cout << "|" << p1 << "|\t== " << p1.DistanceFromOrigin() << endl;
  cout << "|" << p2 << "|\t== " << p2.DistanceFromOrigin() << endl;

  Triple<int,string,list<double> > triple(10,"STRINGY", list<double>());
  // XXX A mountain of errors...
  //   (This happens because a component of the tuple does not have a
  //    corresponding overload of operator<< for an ostream)
  //cout << triple << endl;

  list<Triple<string,string,string> > pimpNames;
  pimpNames.push_back(Triple<string,string,string>("Pimp Daddy", "Athappilly", "Large"));
  pimpNames.push_back(Triple<string,string,string>("Papa", "Cody", "Flow"));
  pimpNames.push_back(Triple<string,string,string>("Mack Master", "Katelin", "Glide"));
  PrintTriples(pimpNames);

  return EXIT_SUCCESS;
}

template <class T1, class T2, class T3>
void PrintTriples(const list<Triple<T1,T2,T3> > triples) {
  cout << "[";
  if (! triples.empty()) {
    // XXX error: need 'typename' before ...  because ... is a dependent scope
    //   (This is due to ambiguity in the C++ grammar over what
    //    exactly are A and B in A::B (i.e. we don't know that B is a
    //    typename until instantiation here)
    // XXX  error: conversion from ... to non-scalar type ... requested
    //   (This is because we declare triples to be a const parameter
    //    but try to grab a non-const iterator for it)
    typename list<Triple<T1,T2,T3> >::const_iterator it = triples.begin();
    cout << *it;
    for (it = ++it; it != triples.end(); ++it)
      cout << ", " << *it;
  }
  cout << "]" << endl;
}