With templates, you can make the type a class works with generic. You have a class that deals with "things" and you can tell it what kind of things.
An example is the vector class that comes with C++.
vectorHere we declare (and initialize a vector of integers. Notice the type inside the angle brackets. That is the syntax for a template class. Note that a C++ vector is an alternative to an array with extra features.vec = {1, 2, 3, 4, 5};
As a user (consumer) of some template class, all you need to know is that you shove the name of the type inside the angle brackets.
#include <cstdio> #include <string> using namespace std; template <typename vtype> class Saver { public: Saver ( vtype arg ) { _bogus = arg; _empty = true; } void save ( vtype ); vtype restore ( void ); private: bool _empty; vtype _thing; vtype _bogus; }; template <typename vtype> inline void Saver<vtype>::save ( vtype xx ) { _thing = xx; _empty = false; } template <typename vtype> inline vtype Saver<vtype>::restore ( void ) { vtype rv; if ( _empty ) rv = _bogus; else rv = _thing; _empty = true; return rv; } int main () { string x; Saver<string> s ( "fooey" ); s.save ( "potatoe" ); x = s.restore (); printf ( "%s\n", x.c_str() ); x = s.restore (); printf ( "%s\n", x.c_str() ); }Even with all of my effort to make this short, it got a bit long. But it is full, working, tested code.
By no means vital, but of passing interest, I use the C++ fundamental "bool" type, and I feel very proud to have done so.
The thing to focus on are the lines with "template". There are three of these and they precede the class definition and the individual method definitions. They indicate that the "virtual type" with be indicated by "vtype" (I could have chosen any name, but I liked "vtype"). I then use this name where the actual type will be substituted by the compiler.
I faced a dilemna when writing the restore method. I wanted to return some kind of "nasty value" if the container was empty, but when any type is possible, how can I put in something like the famous 999 value so often used for integers. I punted by letting the caller specify the bogus value when the object is instantiated. Once you see how "vtype" is specified, the scheme here should be clear enough. Notice that we could write main() like this:
int main () { string x; int n; Saver<string> s ( "fooey" ); s.save ( "potatoe" ); x = s.restore (); printf ( "%s\n", x.c_str() ); x = s.restore (); printf ( "%s\n", x.c_str() ); Saver<int> j ( 999 ); j.save ( 13 ); printf ( "%d\n", j.restore() ); }Here we use the same class, first for strings, then for integers. We could use it for doubles or even classes other than "string" (remember that "string" is just a C++ class, albeit part of the standard library).
Tom's Computer Info / tom@mmto.org