Listing 7: A test program that demonstrates various uses of the ArgumentList class

#include<iostream>
#pragma hdrstop
#include <condefs.h>

#include "arglist.h"

using namespace std ;

void show ( const ArgumentList & args )
{
  cout << "List contents:" << endl ;

  // If your compiler can determine the template 
  // specialization parameter from the left side of the 
  // assigments, you can write: args[0], etc...
  int    i = args.at<int>   (0);
  double d = args.at<double>(1);
  string s = args.at<string>(2);

  cout << "int   : " << i << endl ;
  cout << "double: " << d << endl ;
  cout << "string: " << s << endl ;

  // Used when show() is called from test_recursion().
  if ( args.size() > 3 )
  {
    // The whole list was pushed as the last element.
    const ArgumentList & list = args.at<ArgumentList>(3);
    show ( list ) ;
  }
}
void wrong ( const ArgumentList & args )
{
  cout << "Trying to retrieve the wrong argument." << endl;
  cout << "This will throw invalid_argument" << endl ;
  string s = args.at<string>(0);
}

void test_recursion( ArgumentList & args )
{
  cout << endl << "Testing type-recursion" << endl ;

  cout << "Pushing the list itself as the fourth element." 
       << endl ;
  args.push_back ( args ) ;

  show ( args ) ;
}

void test()
{
  // These variables are allocated in the heap to show
  // how ArgumentList copies the values.
  int    * i = new int    ( 33 ) ;
  double * d = new double ( 3.14 ) ;
  string * s = new string ( "This is a string" ) ;

  // Creates a list with 3 elements.
  ArgumentList args ;
  args.push_back ( *i ) ;
  args.push_back ( *d ) ;
  args.push_back ( *s ) ;

  cout << "Testing ArgumentList." << endl
       << endl
       << "Creating a list with 3 elements:" << endl
       << "int   : " << *i << endl
       << "double: " << *d << endl
       << "string: " << *s << endl ;

  delete i ;
  delete d ;
  delete s ;

  show ( args ) ;

  // wrong() will try to peek up the string at the wrong position.
  try
  {
    wrong ( args ) ;
  }
  catch ( invalid_argument& x )
  {
    cout << "exception invalid_argument: " << x.what() << endl ;
  }

  // This show that ArgumentList can be safely copied.
  cout << endl << "Copying the entire argument list... " << endl ;
  ArgumentList copy = args ;
  show ( copy ) ;

  // This shows that ArgumentList can even contain elements of 
  // type ArgumentList.
  test_recursion(copy) ;
}
void main()
{
  try
  {
    test() ;
  }
  catch ( invalid_argument& x )
  {
    cout << "unexpected exception invalid_argument: " 
         << x.what() << endl ;
  }
  catch ( ... )
  {
    cout << "Unexpected exception" << endl ;
  }
}

/*
OUTPUT:

Testing ArgumentList.

Creating a list with 3 elements:
int   : 33
double: 3.14
string: This is a string
List contents:
int   : 33
double: 3.14
string: This is a string
Trying to retrieve the wrong argument. 
This will throw invalid_argument
exception invalid_argument: string is not a valid type

Copying the entire argument list... 
List contents:
int   : 33
double: 3.14
string: This is a string

Testing type-recursion
Pushing the list itself as the fourth element.
List contents:
int   : 33
double: 3.14
string: This is a string
List contents:
int   : 33
double: 3.14
string: This is a string
*/