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;
}