/* Orion Lawlor's not-so-simple C++ programs.
The non-obfuscated partial-specialization template
metaprogram to spit out the lyrics to "9 bottles of beer".
*/
#include <iostream.h>

/* Print the line for "n bottles of beer" */
template < int n > void print (char *r)
{
  std::cout << n << " bottles of beer" << r;
} 

template <> void print < 1 > (char *r)
{
  std::cout << 1 << " bottle of beer" << r;
} 

template <> void print < 0 > (char *r)
{
  std::cout << "No more" << " bottle" "s" " of beer" << r;
} 

/* Sing the n'th stanza of the song, and all subsequent stanzas */
template < int n > 
void stanza ()
{
  print < n > (" on the wall,\n");
  print < n > (",\nTake one down, pass it around,\n");
  print < n - 1 > (" on the wall.\n\n");
  stanza < n - 1 > ();
} 

/* Base case: last stanza, which is empty. */
template <> void stanza < 0 > () { }

main ()
{
  stanza < 9 > ();
}
/*<@>
<@> ******** Program output: ********
<@> 9 bottles of beer on the wall,
<@> 9 bottles of beer,
<@> Take one down, pass it around,
<@> 8 bottles of beer on the wall.
<@> 
<@> 8 bottles of beer on the wall,
<@> 8 bottles of beer,
<@> Take one down, pass it around,
<@> 7 bottles of beer on the wall.
<@> 
<@> 7 bottles of beer on the wall,
<@> 7 bottles of beer,
<@> Take one down, pass it around,
<@> 6 bottles of beer on the wall.
<@> 
<@> 6 bottles of beer on the wall,
<@> 6 bottles of beer,
<@> Take one down, pass it around,
<@> 5 bottles of beer on the wall.
<@> 
<@> 5 bottles of beer on the wall,
<@> 5 bottles of beer,
<@> Take one down, pass it around,
<@> 4 bottles of beer on the wall.
<@> 
<@> 4 bottles of beer on the wall,
<@> 4 bottles of beer,
<@> Take one down, pass it around,
<@> 3 bottles of beer on the wall.
<@> 
<@> 3 bottles of beer on the wall,
<@> 3 bottles of beer,
<@> Take one down, pass it around,
<@> 2 bottles of beer on the wall.
<@> 
<@> 2 bottles of beer on the wall,
<@> 2 bottles of beer,
<@> Take one down, pass it around,
<@> 1 bottle of beer on the wall.
<@> 
<@> 1 bottle of beer on the wall,
<@> 1 bottle of beer,
<@> Take one down, pass it around,
<@> No more bottles of beer on the wall.
<@> 
<@> */
