struct NodeRec
{
	int             data;
	struct NodeRec* next;
};
typedef struct NodeRec  Node;
struct ListOfInt
{
	Node* head;
	Node* current;
};
void LOI_Initialize(ListOfInt* list);
void LOI_InsertBefore(ListOfInt* list, int data);
void LOI_InsertAfter(ListOfInt* list, int data);
void LOI_DeleteCurrent(ListOfInt* list);
int  LOI_First(ListOfInt* list);
int  LOI_Next(ListOfInt* list);
struct NodeRec
{
	StudRec         data;
	struct NodeRec* next;
};
typedef struct NodeRec  Node;
struct ListOfStudec
{
	Node* head;
	Node* current;
};
void LOSR_Initialize(ListOfStudRec* list);
void LOSR_InsertBefore(ListOfStudRec* list, StudRec data);
void LOSR_InsertAfter(ListOfStudRec* list, StudRec data);
void LOSR_DeleteCurrent(ListOfStudRec* list);
StudRec LOSR_First(ListOfStudRec* list);
StudRec LOSR_Next(ListOfStudRec* list);
#define  DECLARE_LIST_OF(TYPE, PREFIX)			    \
							    \
struct NodeFor##TYPE##Rec				    \
{							    \
	TYPE                       data;		    \
	struct NodeFor##TYPE##Rec* next;		    \
};							    \
							    \
typedef struct NodeFor##TYPE##Rec  NodeFor##Type;           \
							    \
struct ListOf##TYPE					    \
{							    \
	NodeFor##TYPE* head;				    \
	NodeFor##TYPE* current;				    \
};							    \
		    					    \
void PREFIX##_Initialize(ListOf##TYPE* list);		    \
void PREFIX##_InsertBefore(ListOf##TYPE* list, TYPE data);  \
void PREFIX##_InsertAfter(ListOf##TYPE* list, TYPE data);   \
void PREFIX##_DeleteCurrent(ListOf##TYPE* list);	    \
TYPE PREFIX##_First(ListOf##TYPE* list);		    \
TYPE PREFIX##_Next(ListOf##TYPE* list);
template keyword before the class¤
                   to tell the compiler which identifiers are special
        
class ListOfInt
{
public:
	ListOfInt(void);
	void InsertBefore(int data);
	void InsertAfter(int data);
	void DeleteCurrent(void);
	int  First(void);
	int  Next(void);
private:
	struct Node
	{
		int   data;
		Node* next;
	};
	Node* head;
	Node* current;
};
StudRec:
class ListOfStudRec
{
public:
	ListOfStudRec(void);
	void InsertBefore(StudRec data);
	void InsertAfter(StudRec data);
	void DeleteCurrent(void);
	StudRec First(void);
	StudRec Next(void);
private:
	struct Node
	{
		StudRec data;
		Node*   next;
	};
	Node* head;
	Node* current;
};
template <class TYPE>
class ListOf
{
public:
	ListOf(void);
	void InsertBefore(TYPE data);
	void InsertAfter(TYPE data);
	void DeleteCurrent(void);
	TYPE First(void);
	TYPE Next(void);
private:
	struct Node
	{
		TYPE  data;
		Node* next;
	};
	Node* head;
	Node* current;
};
ListOf<...> classes¤
   into existence:
class ListOf<int>;		// EQUIVALENT TO ListOfInt
class ListOf<StudRec>;		// EQUIVALENT TO ListOfStudRec
class ListOf<string>		// CLASS TO STORE string OBJECTS
class ListOf<Target>		// CLASS TO STORE Target OBJECTS
class ListOf<Nominee>;		// IN THE CATEGORY
				// "Best Template in a Supporting Role"
class ListOf<Winner>;		// AND THE WINNER IS...Shirley Template!
class ListOf< ListOf<int> >;	// WOW!
int main(void)
{
	ListOf<double> marks;      // COMPILER CREATES THIS TYPE
	ListOf<int>    ids;        // AND THIS TYPE
	double         nextmark;
	int            nextid;
	while (cin >> nextid >> nextmark)
	{
		ids.InsertAfter(nextid);
		marks.InsertAfter(nextmark);
	}
	// ETC...
};
class keyword
        
template <class KEYTYPE, class DATATYPE>
class AssociativeArray
{
public:
	AssociativeArray(void);
	~AssociativeArray(void);
	DATATYPE& operator[](const KEYTYPE& key);
	ListOf<KEYTYPE>  Keys(void);
	ListOf<DATATYPE> Values(void);
private:
	// MAGIC CODE TO MAKE IT ALL WORK :-)
};
// AND LATER
int main(void)
{
	AssociativeArray<string, double> result;
	result["Jon"]  = 100.0;	// SET THE EXAM
	result["Boris"]   = 49.9;	// WAS DRUNK
	result["Ai Joo"]  = 77.7	// GOOD STUDENT
	result["Damien"]  = 66.6	// EVIL STUDENT
	string name;
	while (cin >> name)
	{
		cout << result[name] << endl;
	}
}
template <int MAXSCORE, int PASSMARK>
class ExamResults
{
public:
	ExamResults(ListOf<ints> ids, ListOf<double> scores);
	~ExamResults(void);
	void PrintPasses(void)
	{
		double nextmark;
		int    nextid;
		while (GetNextMark(nextid,nextmark))
		{
			if (nextmark>=PASSMARK)
			{
				cout << nextid << ": "
				     << nextmark/MAXSCORE*100
				     << endl;
			}
		}
	}
private:
	// MAGIC CODE TO MAKE IT ALL WORK :-)
	bool GetNextResult(int& id, double& mark);
};
// AND LATER
int main(int argc, char* argv[])
{
	ListOf<int>    idlist   = getIDList(argv[0]);
	ListOf<double> marklist = getMarkList(argv[0]);
	ExamResults<100,50> passHalf(idlist, marklist);
	ExamResults<100,90> passReal(idlist, marklist);
	cout << "Normally pass at 50%..." << endl;
	passHalf.PrintPasses();
	cout << "But today pass at 90%..." << endl;
	passReal.PrintPasses();
}
template keyword at
   the start:
template <class DATATYPE>
DATATYPE max(const DATATYPE& d1, const DATATYPE& d2)
{
	return (d1>d2) ? d1 : d2;
}
// AND LATER...
int main(void)
{
	string s1 = "cat";
	string s2 = "dog";
	cout << max(1,2) << endl;
	cout << max(1.1,2.2) << endl;
	cout << max(s1,s2) << endl;
	cout << max("cat","dog") << endl;
	cout << max(1,2.2) << endl;
}
max("cat","dog") causes the template to
   instantiate a function: char* max(char*, char*):
char* max(const char*& d1, const char*& d2)
{
	return (d1>d2) ? d1 : d2;
}
template <>
char* max(const char*& d1, const char*& d2)
{
	return (strcmp(d1,d2)>0) ? d1 : d2;
}
template <long N>
class Factorial
{
public:
	long Value(void) { return N * fn_1.Value(); }
private:
	Factorial<N-1> fn_1;
};
template <>
class Factorial<0>
{
public:
	long Value(void) { return 1; }
};
int main(void)
{
	Factorial<15> f15;
	cout << f15.Value() << endl;
}